d: Merge upstream dmd ff57fec515, druntime ff57fec515, phobos 17bafda79.
[official-gcc.git] / gcc / d / dmd / dsymbolsem.d
blob430377ff874327233be831c4684308606bd2ca20
1 /**
2 * Does the semantic 1 pass on the AST, which looks at symbol declarations but not initializers
3 * or function bodies.
5 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
6 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
7 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbolsem.d, _dsymbolsem.d)
9 * Documentation: https://dlang.org/phobos/dmd_dsymbolsem.html
10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dsymbolsem.d
13 module dmd.dsymbolsem;
15 import core.stdc.stdio;
16 import core.stdc.string;
18 import dmd.aggregate;
19 import dmd.aliasthis;
20 import dmd.arraytypes;
21 import dmd.astcodegen;
22 import dmd.astenums;
23 import dmd.attrib;
24 import dmd.blockexit;
25 import dmd.clone;
26 import dmd.cond;
27 import dmd.compiler;
28 import dmd.dcast;
29 import dmd.dclass;
30 import dmd.declaration;
31 import dmd.denum;
32 import dmd.dimport;
33 import dmd.dinterpret;
34 import dmd.dmangle;
35 import dmd.dmodule;
36 import dmd.dscope;
37 import dmd.dstruct;
38 import dmd.dsymbol;
39 import dmd.dtemplate;
40 import dmd.dversion;
41 import dmd.errors;
42 import dmd.escape;
43 import dmd.expression;
44 import dmd.expressionsem;
45 import dmd.func;
46 import dmd.globals;
47 import dmd.id;
48 import dmd.identifier;
49 import dmd.importc;
50 import dmd.init;
51 import dmd.initsem;
52 import dmd.intrange;
53 import dmd.hdrgen;
54 import dmd.location;
55 import dmd.mtype;
56 import dmd.mustuse;
57 import dmd.nogc;
58 import dmd.nspace;
59 import dmd.objc;
60 import dmd.opover;
61 import dmd.optimize;
62 import dmd.parse;
63 import dmd.root.array;
64 import dmd.root.filename;
65 import dmd.common.outbuffer;
66 import dmd.root.rmem;
67 import dmd.rootobject;
68 import dmd.root.utf;
69 import dmd.semantic2;
70 import dmd.semantic3;
71 import dmd.sideeffect;
72 import dmd.statementsem;
73 import dmd.staticassert;
74 import dmd.tokens;
75 import dmd.utils;
76 import dmd.statement;
77 import dmd.target;
78 import dmd.templateparamsem;
79 import dmd.typesem;
80 import dmd.visitor;
82 version (IN_GCC) {}
83 else version (IN_LLVM) {}
84 else version = MARS;
86 enum LOG = false;
88 package uint setMangleOverride(Dsymbol s, const(char)[] sym)
90 if (s.isFuncDeclaration() || s.isVarDeclaration())
92 s.isDeclaration().mangleOverride = sym;
93 return 1;
96 if (auto ad = s.isAttribDeclaration())
98 uint nestedCount = 0;
100 ad.include(null).foreachDsymbol( (s) { nestedCount += setMangleOverride(s, sym); } );
102 return nestedCount;
104 return 0;
108 * Apply pragma printf/scanf to FuncDeclarations under `s`,
109 * poking through attribute declarations such as `extern(C)`
110 * but not through aggregates or function bodies.
112 * Params:
113 * s = symbol to apply
114 * printf = `true` for printf, `false` for scanf
116 private void setPragmaPrintf(Dsymbol s, bool printf)
118 if (auto fd = s.isFuncDeclaration())
120 fd.printf = printf;
121 fd.scanf = !printf;
124 if (auto ad = s.isAttribDeclaration())
126 ad.include(null).foreachDsymbol( (s) { setPragmaPrintf(s, printf); } );
130 /*************************************
131 * Does semantic analysis on the public face of declarations.
133 extern(C++) void dsymbolSemantic(Dsymbol dsym, Scope* sc)
135 scope v = new DsymbolSemanticVisitor(sc);
136 dsym.accept(v);
139 /***************************************************
140 * Determine the numerical value of the AlignmentDeclaration
141 * Params:
142 * ad = AlignmentDeclaration
143 * sc = context
144 * Returns:
145 * ad with alignment value determined
147 AlignDeclaration getAlignment(AlignDeclaration ad, Scope* sc)
149 if (!ad.salign.isUnknown()) // UNKNOWN is 0
150 return ad;
152 if (!ad.exps)
154 ad.salign.setDefault();
155 return ad;
158 dinteger_t strictest = 0; // strictest alignment
159 bool errors;
160 foreach (ref exp; (*ad.exps)[])
162 sc = sc.startCTFE();
163 auto e = exp.expressionSemantic(sc);
164 e = resolveProperties(sc, e);
165 sc = sc.endCTFE();
166 e = e.ctfeInterpret();
167 exp = e; // could be re-evaluated if exps are assigned to more than one AlignDeclaration by CParser.applySpecifier(),
168 // e.g. `_Alignas(8) int a, b;`
169 if (e.op == EXP.error)
170 errors = true;
171 else
173 auto n = e.toInteger();
174 if (sc.flags & SCOPE.Cfile && n == 0) // C11 6.7.5-6 allows 0 for alignment
175 continue;
177 if (n < 1 || n & (n - 1) || ushort.max < n || !e.type.isintegral())
179 error(ad.loc, "alignment must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
180 errors = true;
182 if (n > strictest) // C11 6.7.5-6
183 strictest = n;
187 if (errors || strictest == 0) // C11 6.7.5-6 says alignment of 0 means no effect
188 ad.salign.setDefault();
189 else
190 ad.salign.set(cast(uint) strictest);
192 return ad;
195 const(char)* getMessage(DeprecatedDeclaration dd)
197 if (auto sc = dd._scope)
199 dd._scope = null;
201 sc = sc.startCTFE();
202 dd.msg = dd.msg.expressionSemantic(sc);
203 dd.msg = resolveProperties(sc, dd.msg);
204 sc = sc.endCTFE();
205 dd.msg = dd.msg.ctfeInterpret();
207 if (auto se = dd.msg.toStringExp())
208 dd.msgstr = se.toStringz().ptr;
209 else
210 error(dd.msg.loc, "compile time constant expected, not `%s`", dd.msg.toChars());
212 return dd.msgstr;
216 // Returns true if a contract can appear without a function body.
217 package bool allowsContractWithoutBody(FuncDeclaration funcdecl)
219 assert(!funcdecl.fbody);
221 /* Contracts can only appear without a body when they are virtual
222 * interface functions or abstract.
224 Dsymbol parent = funcdecl.toParent();
225 InterfaceDeclaration id = parent.isInterfaceDeclaration();
227 if (!funcdecl.isAbstract() &&
228 (funcdecl.fensures || funcdecl.frequires) &&
229 !(id && funcdecl.isVirtual()))
231 auto cd = parent.isClassDeclaration();
232 if (!(cd && cd.isAbstract()))
233 return false;
235 return true;
239 Tests whether the `ctor` that is part of `ti` is an rvalue constructor
240 (i.e. a constructor that receives a single parameter of the same type as
241 `Unqual!typeof(this)`). If that is the case and `sd` contains a copy
242 constructor, than an error is issued.
244 Params:
245 sd = struct declaration that may contin both an rvalue and copy constructor
246 ctor = constructor that will be checked if it is an evalue constructor
247 ti = template instance the ctor is part of
249 Return:
250 `false` if ctor is not an rvalue constructor or if `sd` does not contain a
251 copy constructor. `true` otherwise
253 bool checkHasBothRvalueAndCpCtor(StructDeclaration sd, CtorDeclaration ctor, TemplateInstance ti)
255 auto loc = ctor.loc;
256 auto tf = cast(TypeFunction)ctor.type;
257 auto dim = tf.parameterList.length;
258 if (sd && sd.hasCopyCtor && (dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
260 auto param = tf.parameterList[0];
261 if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
263 .error(loc, "cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars());
264 .errorSupplemental(ti.loc, "Template instance `%s` creates an rvalue constructor for `struct %s`",
265 ti.toPrettyChars(), sd.toChars());
267 return true;
271 return false;
274 private extern(C++) final class DsymbolSemanticVisitor : Visitor
276 alias visit = Visitor.visit;
278 Scope* sc;
279 this(Scope* sc) scope @safe
281 this.sc = sc;
284 // Save the scope and defer semantic analysis on the Dsymbol.
285 private void deferDsymbolSemantic(Dsymbol s, Scope *scx)
287 s._scope = scx ? scx : sc.copy();
288 s._scope.setNoFree();
289 Module.addDeferredSemantic(s);
292 override void visit(Dsymbol dsym)
294 .error(dsym.loc, "%s `%s` %p has no semantic routine", dsym.kind, dsym.toPrettyChars, dsym);
297 override void visit(ScopeDsymbol) { }
298 override void visit(Declaration) { }
300 override void visit(AliasThis dsym)
302 if (dsym.semanticRun != PASS.initial)
303 return;
305 if (dsym._scope)
307 sc = dsym._scope;
308 dsym._scope = null;
311 if (!sc)
312 return;
314 dsym.semanticRun = PASS.semantic;
315 dsym.isDeprecated_ = !!(sc.stc & STC.deprecated_);
317 Dsymbol p = sc.parent.pastMixin();
318 AggregateDeclaration ad = p.isAggregateDeclaration();
319 if (!ad)
321 error(dsym.loc, "alias this can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
322 return;
325 assert(ad.members);
326 Dsymbol s = ad.search(dsym.loc, dsym.ident);
327 if (!s)
329 s = sc.search(dsym.loc, dsym.ident, null);
330 if (s)
331 error(dsym.loc, "`%s` is not a member of `%s`", s.toChars(), ad.toChars());
332 else
333 error(dsym.loc, "undefined identifier `%s`", dsym.ident.toChars());
334 return;
336 if (ad.aliasthis && s != ad.aliasthis)
338 error(dsym.loc, "there can be only one alias this");
339 return;
342 /* disable the alias this conversion so the implicit conversion check
343 * doesn't use it.
345 ad.aliasthis = null;
347 Dsymbol sx = s;
348 if (sx.isAliasDeclaration())
349 sx = sx.toAlias();
350 Declaration d = sx.isDeclaration();
351 if (d && !d.isTupleDeclaration())
353 /* https://issues.dlang.org/show_bug.cgi?id=18429
355 * If the identifier in the AliasThis declaration
356 * is defined later and is a voldemort type, we must
357 * perform semantic on the declaration to deduce the type.
359 if (!d.type)
360 d.dsymbolSemantic(sc);
362 Type t = d.type;
363 assert(t);
364 if (ad.type.implicitConvTo(t) > MATCH.nomatch)
366 error(dsym.loc, "alias this is not reachable as `%s` already converts to `%s`", ad.toChars(), t.toChars());
370 dsym.sym = s;
371 // Restore alias this
372 ad.aliasthis = dsym;
373 dsym.semanticRun = PASS.semanticdone;
376 override void visit(AliasDeclaration dsym)
378 if (dsym.semanticRun >= PASS.semanticdone)
379 return;
380 assert(dsym.semanticRun <= PASS.semantic);
382 if (!sc)
383 return;
385 dsym.semanticRun = PASS.semantic;
387 dsym.storage_class |= sc.stc & STC.deprecated_;
388 dsym.visibility = sc.visibility;
389 dsym.userAttribDecl = sc.userAttribDecl;
391 if (!sc.func && dsym.inNonRoot())
392 return;
394 aliasSemantic(dsym, sc);
397 override void visit(AliasAssign dsym)
399 //printf("visit(AliasAssign)\n");
400 if (dsym.semanticRun >= PASS.semanticdone)
401 return;
402 assert(dsym.semanticRun <= PASS.semantic);
404 if (!sc.func && dsym.inNonRoot())
405 return;
407 aliasAssignSemantic(dsym, sc);
410 override void visit(VarDeclaration dsym)
412 version (none)
414 printf("VarDeclaration::semantic('%s', parent = '%s') sem = %d\n",
415 dsym.toChars(), sc.parent ? sc.parent.toChars() : null, dsym.semanticRun);
416 printf(" type = %s\n", dsym.type ? dsym.type.toChars() : "null");
417 printf(" stc = x%llx\n", dsym.storage_class);
418 printf(" storage_class = x%llx\n", dsym.storage_class);
419 printf("linkage = %d\n", dsym.linkage);
420 //if (strcmp(toChars(), "mul") == 0) assert(0);
422 //if (semanticRun > PASS.initial)
423 // return;
424 //semanticRun = PSSsemantic;
426 if (dsym.semanticRun >= PASS.semanticdone)
427 return;
429 if (sc && sc.inunion && sc.inunion.isAnonDeclaration())
430 dsym.overlapped = true;
432 dsym.sequenceNumber = global.varSequenceNumber++;
433 if (!dsym.isScope())
434 dsym.maybeScope = true;
436 Scope* scx = null;
437 if (dsym._scope)
439 sc = dsym._scope;
440 scx = sc;
441 dsym._scope = null;
444 if (!sc)
445 return;
447 dsym.semanticRun = PASS.semantic;
449 // 'static foreach' variables should not inherit scope properties
450 // https://issues.dlang.org/show_bug.cgi?id=19482
451 if ((dsym.storage_class & (STC.foreach_ | STC.local)) == (STC.foreach_ | STC.local))
453 dsym._linkage = LINK.d;
454 dsym.visibility = Visibility(Visibility.Kind.public_);
455 dsym.overlapped = false; // unset because it is modified early on this function
456 dsym.userAttribDecl = null; // unset because it is set by Dsymbol.setScope()
458 else
460 /* Pick up storage classes from context, but except synchronized,
461 * override, abstract, and final.
463 dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
464 dsym.userAttribDecl = sc.userAttribDecl;
465 dsym.cppnamespace = sc.namespace;
466 dsym._linkage = sc.linkage;
467 dsym.visibility = sc.visibility;
468 dsym.alignment = sc.alignment();
471 if (dsym.storage_class & STC.extern_ && dsym._init)
472 .error(dsym.loc, "%s `%s` extern symbols cannot have initializers", dsym.kind, dsym.toPrettyChars);
474 AggregateDeclaration ad = dsym.isThis();
475 if (ad)
476 dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
478 /* If auto type inference, do the inference
480 int inferred = 0;
481 if (!dsym.type)
483 dsym.inuse++;
485 // Infering the type requires running semantic,
486 // so mark the scope as ctfe if required
487 bool needctfe = (dsym.storage_class & (STC.manifest | STC.static_)) != 0 || !sc.func;
488 if (needctfe)
490 sc.flags |= SCOPE.condition;
491 sc = sc.startCTFE();
493 //printf("inferring type for %s with init %s\n", dsym.toChars(), dsym._init.toChars());
494 dsym._init = dsym._init.inferType(sc);
495 dsym.type = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0).type;
496 if (needctfe)
497 sc = sc.endCTFE();
499 dsym.inuse--;
500 inferred = 1;
502 /* This is a kludge to support the existing syntax for RAII
503 * declarations.
505 dsym.storage_class &= ~STC.auto_;
506 dsym.originalType = dsym.type.syntaxCopy();
508 else
510 if (!dsym.originalType)
511 dsym.originalType = dsym.type.syntaxCopy();
513 /* Prefix function attributes of variable declaration can affect
514 * its type:
515 * pure nothrow void function() fp;
516 * static assert(is(typeof(fp) == void function() pure nothrow));
518 Scope* sc2 = sc.push();
519 sc2.stc |= (dsym.storage_class & STC.FUNCATTR);
520 dsym.inuse++;
521 dsym.type = dsym.type.typeSemantic(dsym.loc, sc2);
522 dsym.inuse--;
523 sc2.pop();
525 //printf(" semantic type = %s\n", dsym.type ? dsym.type.toChars() : "null");
526 if (dsym.type.ty == Terror)
527 dsym.errors = true;
529 dsym.type.checkDeprecated(dsym.loc, sc);
530 dsym.parent = sc.parent;
531 //printf("this = %p, parent = %p, '%s'\n", dsym, dsym.parent, dsym.parent.toChars());
533 /* If scope's alignment is the default, use the type's alignment,
534 * otherwise the scope overrrides.
536 if (dsym.alignment.isDefault())
537 dsym.alignment = dsym.type.alignment(); // use type's alignment
539 //printf("sc.stc = %x\n", sc.stc);
540 //printf("storage_class = x%x\n", storage_class);
542 dsym.type.checkComplexTransition(dsym.loc, sc);
544 // Calculate type size + safety checks
545 if (dsym.storage_class & STC.gshared && !dsym.isMember())
547 sc.setUnsafe(false, dsym.loc, "__gshared not allowed in safe functions; use shared");
550 Dsymbol parent = dsym.toParent();
552 Type tb = dsym.type.toBasetype();
553 Type tbn = tb.baseElemOf();
554 if (tb.ty == Tvoid && !(dsym.storage_class & STC.lazy_))
556 if (inferred)
558 .error(dsym.loc, "%s `%s` - type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`",
559 dsym.kind, dsym.toPrettyChars, dsym.type.toChars(), toChars(dsym._init));
561 else
562 .error(dsym.loc, "%s `%s` - variables cannot be of type `void`", dsym.kind, dsym.toPrettyChars);
563 dsym.type = Type.terror;
564 tb = dsym.type;
566 if (tb.ty == Tfunction)
568 .error(dsym.loc, "%s `%s` cannot be declared to be a function", dsym.kind, dsym.toPrettyChars);
569 dsym.type = Type.terror;
570 tb = dsym.type;
572 if (auto ts = tb.isTypeStruct())
574 // Require declarations, except when it's just a reference (as done for pointers)
575 // or when the variable is defined externally
576 if (!ts.sym.members && !(dsym.storage_class & (STC.ref_ | STC.extern_)))
578 .error(dsym.loc, "%s `%s` - no definition of struct `%s`", dsym.kind, dsym.toPrettyChars, ts.toChars());
580 // Explain why the definition is required when it's part of another type
581 if (!dsym.type.isTypeStruct())
583 // Prefer Loc of the dependant type
584 const s = dsym.type.toDsymbol(sc);
585 const loc = (s ? s : dsym).loc;
586 loc.errorSupplemental("required by type `%s`", dsym.type.toChars());
588 errorSupplemental(dsym.loc, "see https://dlang.org/spec/struct.html#opaque_struct_unions");
589 errorSupplemental(dsym.loc, "perhaps declare a variable with pointer type `%s*` instead", dsym.type.toChars());
591 // Flag variable as error to avoid invalid error messages due to unknown size
592 dsym.type = Type.terror;
595 if ((dsym.storage_class & STC.auto_) && !inferred)
596 .error(dsym.loc, "%s `%s` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?", dsym.kind, dsym.toPrettyChars);
598 if (auto tt = tb.isTypeTuple())
600 /* Instead, declare variables for each of the tuple elements
601 * and add those.
603 size_t nelems = Parameter.dim(tt.arguments);
604 Expression ie = (dsym._init && !dsym._init.isVoidInitializer()) ? dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0) : null;
605 if (ie)
606 ie = ie.expressionSemantic(sc);
607 if (nelems > 0 && ie)
609 auto iexps = new Expressions();
610 iexps.push(ie);
611 auto exps = new Expressions();
612 for (size_t pos = 0; pos < iexps.length; pos++)
614 Lexpand1:
615 Expression e = (*iexps)[pos];
616 Parameter arg = Parameter.getNth(tt.arguments, pos);
617 arg.type = arg.type.typeSemantic(dsym.loc, sc);
618 //printf("[%d] iexps.length = %d, ", pos, iexps.length);
619 //printf("e = (%s %s, %s), ", Token.tochars[e.op], e.toChars(), e.type.toChars());
620 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
622 if (e != ie)
624 if (iexps.length > nelems)
625 goto Lnomatch;
626 if (e.type.implicitConvTo(arg.type))
627 continue;
630 if (auto te = e.isTupleExp())
632 if (iexps.length - 1 + te.exps.length > nelems)
633 goto Lnomatch;
635 iexps.remove(pos);
636 iexps.insert(pos, te.exps);
637 (*iexps)[pos] = Expression.combine(te.e0, (*iexps)[pos]);
638 goto Lexpand1;
640 else if (isAliasThisTuple(e))
642 auto v = copyToTemp(0, "__tup", e);
643 v.dsymbolSemantic(sc);
644 auto ve = new VarExp(dsym.loc, v);
645 ve.type = e.type;
647 exps.setDim(1);
648 (*exps)[0] = ve;
649 expandAliasThisTuples(exps, 0);
651 for (size_t u = 0; u < exps.length; u++)
653 Lexpand2:
654 Expression ee = (*exps)[u];
655 arg = Parameter.getNth(tt.arguments, pos + u);
656 arg.type = arg.type.typeSemantic(dsym.loc, sc);
657 //printf("[%d+%d] exps.length = %d, ", pos, u, exps.length);
658 //printf("ee = (%s %s, %s), ", Token.tochars[ee.op], ee.toChars(), ee.type.toChars());
659 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
661 size_t iexps_dim = iexps.length - 1 + exps.length;
662 if (iexps_dim > nelems)
663 goto Lnomatch;
664 if (ee.type.implicitConvTo(arg.type))
665 continue;
667 if (expandAliasThisTuples(exps, u) != -1)
668 goto Lexpand2;
671 if ((*exps)[0] != ve)
673 Expression e0 = (*exps)[0];
674 (*exps)[0] = new CommaExp(dsym.loc, new DeclarationExp(dsym.loc, v), e0);
675 (*exps)[0].type = e0.type;
677 iexps.remove(pos);
678 iexps.insert(pos, exps);
679 goto Lexpand1;
683 if (iexps.length < nelems)
684 goto Lnomatch;
686 ie = new TupleExp(dsym._init.loc, iexps);
688 Lnomatch:
690 if (ie && ie.op == EXP.tuple)
692 auto te = ie.isTupleExp();
693 size_t tedim = te.exps.length;
694 if (tedim != nelems)
696 error(dsym.loc, "sequence of %d elements cannot be assigned to sequence of %d elements", cast(int)tedim, cast(int)nelems);
697 for (size_t u = tedim; u < nelems; u++) // fill dummy expression
698 te.exps.push(ErrorExp.get());
702 auto exps = new Objects(nelems);
703 for (size_t i = 0; i < nelems; i++)
705 Parameter arg = Parameter.getNth(tt.arguments, i);
707 OutBuffer buf;
708 buf.printf("__%s_field_%llu", dsym.ident.toChars(), cast(ulong)i);
709 auto id = Identifier.idPool(buf[]);
711 Initializer ti;
712 if (ie)
714 Expression einit = ie;
715 if (auto te = ie.isTupleExp())
717 einit = (*te.exps)[i];
718 if (i == 0)
719 einit = Expression.combine(te.e0, einit);
721 ti = new ExpInitializer(einit.loc, einit);
723 else
724 ti = dsym._init ? dsym._init.syntaxCopy() : null;
726 StorageClass storage_class = STC.temp | dsym.storage_class;
727 if ((dsym.storage_class & STC.parameter) && (arg.storageClass & STC.parameter))
728 storage_class |= arg.storageClass;
729 auto v = new VarDeclaration(dsym.loc, arg.type, id, ti, storage_class);
730 //printf("declaring field %s of type %s\n", v.toChars(), v.type.toChars());
731 v.overlapped = dsym.overlapped;
733 v.dsymbolSemantic(sc);
735 Expression e = new VarExp(dsym.loc, v);
736 (*exps)[i] = e;
738 auto v2 = new TupleDeclaration(dsym.loc, dsym.ident, exps);
739 v2.parent = dsym.parent;
740 v2.isexp = true;
741 dsym.aliasTuple = v2;
742 dsym.semanticRun = PASS.semanticdone;
743 return;
746 /* Storage class can modify the type
748 dsym.type = dsym.type.addStorageClass(dsym.storage_class);
750 /* Adjust storage class to reflect type
752 if (dsym.type.isConst())
754 dsym.storage_class |= STC.const_;
755 if (dsym.type.isShared())
756 dsym.storage_class |= STC.shared_;
758 else if (dsym.type.isImmutable())
759 dsym.storage_class |= STC.immutable_;
760 else if (dsym.type.isShared())
761 dsym.storage_class |= STC.shared_;
762 else if (dsym.type.isWild())
763 dsym.storage_class |= STC.wild;
765 if (StorageClass stc = dsym.storage_class & (STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_))
767 if (stc == STC.final_)
768 .error(dsym.loc, "%s `%s` cannot be `final`, perhaps you meant `const`?", dsym.kind, dsym.toPrettyChars);
769 else
771 OutBuffer buf;
772 stcToBuffer(buf, stc);
773 .error(dsym.loc, "%s `%s` cannot be `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
775 dsym.storage_class &= ~stc; // strip off
778 // At this point we can add `scope` to the STC instead of `in`,
779 // because we are never going to use this variable's STC for user messages
780 if (dsym.storage_class & STC.in_ && global.params.previewIn)
781 dsym.storage_class |= STC.scope_;
783 if (dsym.storage_class & STC.scope_)
785 StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
786 if (stc)
788 OutBuffer buf;
789 stcToBuffer(buf, stc);
790 .error(dsym.loc, "%s `%s` cannot be `scope` and `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
792 else if (dsym.isMember())
794 error(dsym.loc, "field `%s` cannot be `scope`", dsym.toChars());
796 else if (!dsym.type.hasPointers())
798 dsym.storage_class &= ~STC.scope_; // silently ignore; may occur in generic code
799 // https://issues.dlang.org/show_bug.cgi?id=23168
800 if (dsym.storage_class & STC.returnScope)
802 dsym.storage_class &= ~(STC.return_ | STC.returnScope);
807 if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe))
810 else
812 AggregateDeclaration aad = parent.isAggregateDeclaration();
813 if (aad)
815 if (global.params.v.field && dsym.storage_class & (STC.const_ | STC.immutable_) && dsym._init && !dsym._init.isVoidInitializer())
817 const(char)* s = (dsym.storage_class & STC.immutable_) ? "immutable" : "const";
818 message(dsym.loc, "`%s.%s` is `%s` field", ad.toPrettyChars(), dsym.toChars(), s);
820 dsym.storage_class |= STC.field;
821 if (auto ts = tbn.isTypeStruct())
822 if (ts.sym.noDefaultCtor)
824 if (!dsym.isThisDeclaration() && !dsym._init)
825 aad.noDefaultCtor = true;
829 InterfaceDeclaration id = parent.isInterfaceDeclaration();
830 if (id)
832 error(dsym.loc, "field `%s` not allowed in interface", dsym.toChars());
834 else if (aad && aad.sizeok == Sizeok.done)
836 error(dsym.loc, "cannot declare field `%s` because it will change the determined size of `%s`", dsym.toChars(), aad.toChars());
839 /* Templates cannot add fields to aggregates
841 TemplateInstance ti = parent.isTemplateInstance();
842 if (ti)
844 // Take care of nested templates
845 while (1)
847 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
848 if (!ti2)
849 break;
850 ti = ti2;
852 // If it's a member template
853 AggregateDeclaration ad2 = ti.tempdecl.isMember();
854 if (ad2 && dsym.storage_class != STC.undefined_)
856 .error(dsym.loc, "%s `%s` - cannot use template to add field to aggregate `%s`", dsym.kind, dsym.toPrettyChars, ad2.toChars());
861 /* If the alignment of a stack local is greater than the stack alignment,
862 * note it in the enclosing function's alignSectionVars
864 version (MARS)
866 if (!dsym.alignment.isDefault() && sc.func &&
867 dsym.alignment.get() > target.stackAlign() &&
868 sc.func && !dsym.isDataseg() && !dsym.isParameter() && !dsym.isField())
870 auto fd = sc.func;
871 if (!fd.alignSectionVars)
872 fd.alignSectionVars = new VarDeclarations();
873 fd.alignSectionVars.push(dsym);
877 if ((dsym.storage_class & (STC.ref_ | STC.parameter | STC.foreach_ | STC.temp | STC.result)) == STC.ref_ && dsym.ident != Id.This)
879 .error(dsym.loc, "%s `%s` - only parameters, functions and `foreach` declarations can be `ref`", dsym.kind, dsym.toPrettyChars);
882 if (dsym.type.hasWild())
884 if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
886 .error(dsym.loc, "%s `%s` - only parameters or stack-based variables can be `inout`", dsym.kind, dsym.toPrettyChars);
888 FuncDeclaration func = sc.func;
889 if (func)
891 if (func.fes)
892 func = func.fes.func;
893 bool isWild = false;
894 for (FuncDeclaration fd = func; fd; fd = fd.toParentDecl().isFuncDeclaration())
896 if (fd.type.isTypeFunction().iswild)
898 isWild = true;
899 break;
902 if (!isWild)
904 .error(dsym.loc, "%s `%s` - `inout` variables can only be declared inside `inout` functions", dsym.kind, dsym.toPrettyChars);
909 if (!(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.ref_ | STC.result)) &&
910 tbn.ty == Tstruct && tbn.isTypeStruct().sym.noDefaultCtor)
912 if (!dsym._init)
914 if (dsym.isField())
916 /* For fields, we'll check the constructor later to make sure it is initialized
918 dsym.storage_class |= STC.nodefaultctor;
920 else if (dsym.storage_class & STC.parameter)
923 else
924 .error(dsym.loc, "%s `%s` - default construction is disabled for type `%s`", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
928 FuncDeclaration fd = parent.isFuncDeclaration();
929 if (dsym.type.isscope() && !(dsym.storage_class & STC.nodtor))
931 if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.gshared) || !fd)
933 .error(dsym.loc, "%s `%s` globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`", dsym.kind, dsym.toPrettyChars);
936 // @@@DEPRECATED_2.097@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
937 // Deprecated in 2.087
938 // Remove this when the feature is removed from the language
939 if (!(dsym.storage_class & STC.scope_))
941 if (!(dsym.storage_class & STC.parameter) && dsym.ident != Id.withSym)
942 .error(dsym.loc, "%s `%s` reference to `scope class` must be `scope`", dsym.kind, dsym.toPrettyChars);
946 // Calculate type size + safety checks
947 if (sc && sc.func)
949 if (dsym._init && dsym._init.isVoidInitializer())
952 if (dsym.type.hasPointers()) // also computes type size
953 sc.setUnsafe(false, dsym.loc,
954 "`void` initializers for pointers not allowed in safe functions");
955 else if (dsym.type.hasInvariant())
956 sc.setUnsafe(false, dsym.loc,
957 "`void` initializers for structs with invariants are not allowed in safe functions");
958 else if (dsym.type.hasSystemFields())
959 sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc,
960 "`void` initializers for `@system` variables not allowed in safe functions");
962 else if (!dsym._init &&
963 !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
964 dsym.type.hasVoidInitPointers())
966 sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions");
970 if ((!dsym._init || dsym._init.isVoidInitializer) && !fd)
972 // If not mutable, initializable by constructor only
973 dsym.setInCtorOnly = true;
976 if (dsym._init)
977 { } // remember we had an explicit initializer
978 else if (dsym.storage_class & STC.manifest)
979 .error(dsym.loc, "%s `%s` - manifest constants must have initializers", dsym.kind, dsym.toPrettyChars);
981 // Don't allow non-extern, non-__gshared variables to be interfaced with C++
982 if (dsym._linkage == LINK.cpp && !(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.gshared)) && dsym.isDataseg())
984 const char* p = (dsym.storage_class & STC.shared_) ? "shared" : "static";
985 .error(dsym.loc, "%s `%s` cannot have `extern(C++)` linkage because it is `%s`", dsym.kind, dsym.toPrettyChars, p);
986 errorSupplemental(dsym.loc, "perhaps declare it as `__gshared` instead");
987 dsym.errors = true;
990 bool isBlit = false;
991 uinteger_t sz;
992 if (sc.flags & SCOPE.Cfile && !dsym._init)
994 addDefaultCInitializer(dsym);
996 if (!dsym._init &&
997 !(dsym.storage_class & (STC.static_ | STC.gshared | STC.extern_)) &&
998 fd &&
999 (!(dsym.storage_class & (STC.field | STC.in_ | STC.foreach_ | STC.parameter | STC.result)) ||
1000 (dsym.storage_class & STC.out_)) &&
1001 (sz = dsym.type.size()) != 0)
1003 // Provide a default initializer
1005 //printf("Providing default initializer for '%s'\n", dsym.toChars());
1006 if (sz == SIZE_INVALID && dsym.type.ty != Terror)
1007 .error(dsym.loc, "%s `%s` - size of type `%s` is invalid", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1009 Type tv = dsym.type;
1010 while (tv.ty == Tsarray) // Don't skip Tenum
1011 tv = tv.nextOf();
1012 if (tv.needsNested())
1014 /* Nested struct requires valid enclosing frame pointer.
1015 * In StructLiteralExp::toElem(), it's calculated.
1017 assert(tbn.ty == Tstruct);
1018 checkFrameAccess(dsym.loc, sc, tbn.isTypeStruct().sym);
1020 Expression e = tv.defaultInitLiteral(dsym.loc);
1021 e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1022 e = e.expressionSemantic(sc);
1023 dsym._init = new ExpInitializer(dsym.loc, e);
1024 goto Ldtor;
1026 if (tv.ty == Tstruct && tv.isTypeStruct().sym.zeroInit)
1028 /* If a struct is all zeros, as a special case
1029 * set its initializer to the integer 0.
1030 * In AssignExp::toElem(), we check for this and issue
1031 * a memset() to initialize the struct.
1032 * Must do same check in interpreter.
1034 Expression e = IntegerExp.literal!0;
1035 e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1036 e.type = dsym.type; // don't type check this, it would fail
1037 dsym._init = new ExpInitializer(dsym.loc, e);
1038 goto Ldtor;
1040 if (dsym.type.baseElemOf().ty == Tvoid)
1042 .error(dsym.loc, "%s `%s` of type `%s` does not have a default initializer", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1044 else if (auto e = dsym.type.defaultInit(dsym.loc))
1046 dsym._init = new ExpInitializer(dsym.loc, e);
1049 // Default initializer is always a blit
1050 isBlit = true;
1052 if (dsym._init)
1054 sc = sc.push();
1055 sc.stc &= ~(STC.TYPECTOR | STC.pure_ | STC.nothrow_ | STC.nogc | STC.ref_ | STC.disable);
1057 if (sc.flags & SCOPE.Cfile &&
1058 dsym.type.isTypeSArray() &&
1059 dsym.type.isTypeSArray().isIncomplete() &&
1060 dsym._init.isVoidInitializer() &&
1061 !(dsym.storage_class & STC.field))
1063 .error(dsym.loc, "%s `%s` - incomplete array type must have initializer", dsym.kind, dsym.toPrettyChars);
1066 ExpInitializer ei = dsym._init.isExpInitializer();
1068 if (ei) // https://issues.dlang.org/show_bug.cgi?id=13424
1069 // Preset the required type to fail in FuncLiteralDeclaration::semantic3
1070 ei.exp = inferType(ei.exp, dsym.type);
1072 // If inside function, there is no semantic3() call
1073 if (sc.func || sc.intypeof == 1)
1075 // If local variable, use AssignExp to handle all the various
1076 // possibilities.
1077 if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
1079 //printf("fd = '%s', var = '%s'\n", fd.toChars(), dsym.toChars());
1080 if (!ei)
1082 ArrayInitializer ai = dsym._init.isArrayInitializer();
1083 Expression e;
1084 if (ai && tb.ty == Taarray)
1085 e = ai.toAssocArrayLiteral();
1086 else
1087 e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
1088 if (!e)
1090 // Run semantic, but don't need to interpret
1091 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITnointerpret);
1092 e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
1093 if (!e)
1095 .error(dsym.loc, "%s `%s` is not a static and cannot have static initializer", dsym.kind, dsym.toPrettyChars);
1096 e = ErrorExp.get();
1099 ei = new ExpInitializer(dsym._init.loc, e);
1100 dsym._init = ei;
1102 else if (sc.flags & SCOPE.Cfile && dsym.type.isTypeSArray() &&
1103 dsym.type.isTypeSArray().isIncomplete())
1105 // C11 6.7.9-22 determine the size of the incomplete array,
1106 // or issue an error that the initializer is invalid.
1107 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
1110 if (ei && dsym.isScope())
1112 Expression ex = ei.exp.lastComma();
1113 if (ex.op == EXP.blit || ex.op == EXP.construct)
1114 ex = (cast(AssignExp)ex).e2;
1115 if (auto ne = ex.isNewExp())
1117 /* See if initializer is a NewExp that can be allocated on the stack.
1119 if (dsym.type.toBasetype().ty == Tclass)
1121 /* Unsafe to allocate on stack if constructor is not `scope` because the `this` can leak.
1122 * https://issues.dlang.org/show_bug.cgi?id=23145
1124 if (ne.member && !(ne.member.storage_class & STC.scope_))
1126 import dmd.escape : setUnsafeDIP1000;
1127 const inSafeFunc = sc.func && sc.func.isSafeBypassingInference(); // isSafeBypassingInference may call setUnsafe().
1128 if (sc.setUnsafeDIP1000(false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym))
1129 errorSupplemental(ne.member.loc, "is the location of the constructor");
1131 ne.onstack = 1;
1132 dsym.onstack = true;
1135 else if (auto fe = ex.isFuncExp())
1137 // or a delegate that doesn't escape a reference to the function
1138 FuncDeclaration f = fe.fd;
1139 if (f.tookAddressOf)
1140 f.tookAddressOf--;
1142 else if (auto ale = ex.isArrayLiteralExp())
1144 // or an array literal assigned to a `scope` variable
1145 if (sc.useDIP1000 == FeatureState.enabled
1146 && !dsym.type.nextOf().needsDestruction())
1147 ale.onstack = true;
1151 Expression exp = ei.exp;
1152 Expression e1 = new VarExp(dsym.loc, dsym);
1153 if (isBlit)
1154 exp = new BlitExp(dsym.loc, e1, exp);
1155 else
1156 exp = new ConstructExp(dsym.loc, e1, exp);
1157 dsym.canassign++;
1158 exp = exp.expressionSemantic(sc);
1159 dsym.canassign--;
1160 exp = exp.optimize(WANTvalue);
1161 if (exp.op == EXP.error)
1163 dsym._init = new ErrorInitializer();
1164 ei = null;
1166 else
1167 ei.exp = exp;
1169 else
1171 // https://issues.dlang.org/show_bug.cgi?id=14166
1172 // Don't run CTFE for the temporary variables inside typeof
1173 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret);
1174 import dmd.semantic2 : lowerStaticAAs;
1175 lowerStaticAAs(dsym, sc);
1176 const init_err = dsym._init.isExpInitializer();
1177 if (init_err && init_err.exp.op == EXP.showCtfeContext)
1179 errorSupplemental(dsym.loc, "compile time context created here");
1183 else if (parent.isAggregateDeclaration())
1185 dsym._scope = scx ? scx : sc.copy();
1186 dsym._scope.setNoFree();
1188 else if (dsym.storage_class & (STC.const_ | STC.immutable_ | STC.manifest) ||
1189 dsym.type.isConst() || dsym.type.isImmutable() ||
1190 sc.flags & SCOPE.Cfile)
1192 /* Because we may need the results of a const declaration in a
1193 * subsequent type, such as an array dimension, before semantic2()
1194 * gets ordinarily run, try to run semantic2() now.
1195 * If a C array is of unknown size, the initializer can provide the size. Do this
1196 * eagerly because C does it eagerly.
1197 * Ignore failure.
1199 if (!inferred)
1201 uint errors = global.errors;
1202 dsym.inuse++;
1203 // Bug 20549. Don't try this on modules or packages, syntaxCopy
1204 // could crash (inf. recursion) on a mod/pkg referencing itself
1205 if (ei && (ei.exp.op != EXP.scope_ ? true : !ei.exp.isScopeExp().sds.isPackage()))
1207 if (ei.exp.type)
1209 // If exp is already resolved we are done, our original init exp
1210 // could have a type painting that we need to respect
1211 // e.g. ['a'] typed as string, or [['z'], ""] as string[]
1212 // See https://issues.dlang.org/show_bug.cgi?id=15711
1214 else
1216 Expression exp = ei.exp.syntaxCopy();
1218 bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
1219 if (needctfe)
1220 sc = sc.startCTFE();
1221 sc = sc.push();
1222 sc.varDecl = dsym; // https://issues.dlang.org/show_bug.cgi?id=24051
1223 exp = exp.expressionSemantic(sc);
1224 exp = resolveProperties(sc, exp);
1225 sc = sc.pop();
1226 if (needctfe)
1227 sc = sc.endCTFE();
1228 ei.exp = exp;
1231 Type tb2 = dsym.type.toBasetype();
1232 Type ti = ei.exp.type.toBasetype();
1234 /* The problem is the following code:
1235 * struct CopyTest {
1236 * double x;
1237 * this(double a) { x = a * 10.0;}
1238 * this(this) { x += 2.0; }
1240 * const CopyTest z = CopyTest(5.3); // ok
1241 * const CopyTest w = z; // not ok, postblit not run
1242 * static assert(w.x == 55.0);
1243 * because the postblit doesn't get run on the initialization of w.
1245 if (auto ts = ti.isTypeStruct())
1247 StructDeclaration sd = ts.sym;
1248 /* Look to see if initializer involves a copy constructor
1249 * (which implies a postblit)
1251 // there is a copy constructor
1252 // and exp is the same struct
1253 if (sd.postblit && tb2.toDsymbol(null) == sd)
1255 // The only allowable initializer is a (non-copy) constructor
1256 if (ei.exp.isLvalue())
1257 .error(dsym.loc, "%s `%s` of type struct `%s` uses `this(this)`, which is not allowed in static initialization", dsym.kind, dsym.toPrettyChars, tb2.toChars());
1262 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
1263 dsym.inuse--;
1264 if (global.errors > errors)
1266 dsym._init = new ErrorInitializer();
1267 dsym.type = Type.terror;
1270 else
1272 dsym._scope = scx ? scx : sc.copy();
1273 dsym._scope.setNoFree();
1276 sc = sc.pop();
1279 Ldtor:
1280 /* Build code to execute destruction, if necessary
1282 dsym.edtor = dsym.callScopeDtor(sc);
1283 if (dsym.edtor)
1285 if (sc.func && dsym.storage_class & (STC.static_ | STC.gshared))
1286 dsym.edtor = dsym.edtor.expressionSemantic(sc._module._scope);
1287 else
1288 dsym.edtor = dsym.edtor.expressionSemantic(sc);
1290 version (none)
1292 // currently disabled because of std.stdio.stdin, stdout and stderr
1293 if (dsym.isDataseg() && !(dsym.storage_class & STC.extern_))
1294 .error(dsym.loc, "%s `%s` static storage variables cannot have destructors", dsym.kind, dsym.toPrettyChars);
1298 dsym.semanticRun = PASS.semanticdone;
1300 if (dsym.type.toBasetype().ty == Terror)
1301 dsym.errors = true;
1303 if(sc.scopesym && !sc.scopesym.isAggregateDeclaration())
1305 for (ScopeDsymbol sym = sc.scopesym; sym && dsym.endlinnum == 0;
1306 sym = sym.parent ? sym.parent.isScopeDsymbol() : null)
1307 dsym.endlinnum = sym.endlinnum;
1311 override void visit(TypeInfoDeclaration dsym)
1313 assert(dsym._linkage == LINK.c);
1316 override void visit(BitFieldDeclaration dsym)
1318 //printf("BitField::semantic('%s')\n", dsym.toChars());
1319 if (dsym.semanticRun >= PASS.semanticdone)
1320 return;
1322 visit(cast(VarDeclaration)dsym);
1323 if (dsym.errors)
1324 return;
1326 if (!(global.params.bitfields || sc.flags & SCOPE.Cfile))
1328 version (IN_GCC)
1329 .error(dsym.loc, "%s `%s` use `-fpreview=bitfields` for bitfield support", dsym.kind, dsym.toPrettyChars);
1330 else
1331 .error(dsym.loc, "%s `%s` use -preview=bitfields for bitfield support", dsym.kind, dsym.toPrettyChars);
1334 if (!dsym.parent.isStructDeclaration() && !dsym.parent.isClassDeclaration())
1336 .error(dsym.loc, "%s `%s` - bit-field must be member of struct, union, or class", dsym.kind, dsym.toPrettyChars);
1339 sc = sc.startCTFE();
1340 auto width = dsym.width.expressionSemantic(sc);
1341 sc = sc.endCTFE();
1342 width = width.ctfeInterpret();
1343 if (!dsym.type.isintegral())
1345 // C11 6.7.2.1-5
1346 error(width.loc, "bit-field type `%s` is not an integer type", dsym.type.toChars());
1347 dsym.errors = true;
1349 if (!width.isIntegerExp())
1351 error(width.loc, "bit-field width `%s` is not an integer constant", dsym.width.toChars());
1352 dsym.errors = true;
1354 const uwidth = width.toInteger(); // uwidth is unsigned
1355 if (uwidth == 0 && !dsym.isAnonymous())
1357 error(width.loc, "bit-field `%s` has zero width", dsym.toChars());
1358 dsym.errors = true;
1360 const sz = dsym.type.size();
1361 if (sz == SIZE_INVALID)
1362 dsym.errors = true;
1363 const max_width = sz * 8;
1364 if (uwidth > max_width)
1366 error(width.loc, "width `%lld` of bit-field `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
1367 dsym.errors = true;
1369 dsym.fieldWidth = cast(uint)uwidth;
1372 override void visit(Import imp)
1374 static if (LOG)
1376 printf("Import::semantic('%s') %s\n", imp.toPrettyChars(), imp.id.toChars());
1377 scope(exit)
1378 printf("-Import::semantic('%s'), pkg = %p\n", imp.toChars(), imp.pkg);
1380 if (imp.semanticRun > PASS.initial)
1381 return;
1383 if (imp._scope)
1385 sc = imp._scope;
1386 imp._scope = null;
1388 if (!sc)
1389 return;
1391 imp.parent = sc.parent;
1393 imp.semanticRun = PASS.semantic;
1395 // Load if not already done so
1396 if (!imp.mod)
1398 // https://issues.dlang.org/show_bug.cgi?id=22857
1399 // if parser errors occur when loading a module
1400 // we should just stop compilation
1401 if (imp.load(sc))
1403 for (size_t i = 0; i < imp.aliasdecls.length; i++)
1404 imp.aliasdecls[i].type = Type.terror;
1405 return;
1408 if (imp.mod)
1410 imp.mod.importAll(null);
1411 imp.mod.checkImportDeprecation(imp.loc, sc);
1414 if (imp.mod)
1416 // Modules need a list of each imported module
1418 // if inside a template instantiation, the instantianting
1419 // module gets the import.
1420 // https://issues.dlang.org/show_bug.cgi?id=17181
1421 Module importer = sc._module;
1422 if (sc.minst && sc.tinst)
1424 importer = sc.minst;
1425 if (!sc.tinst.importedModules.contains(imp.mod))
1426 sc.tinst.importedModules.push(imp.mod);
1428 //printf("%s imports %s\n", importer.toChars(), imp.mod.toChars());
1429 if (!importer.aimports.contains(imp.mod))
1430 importer.aimports.push(imp.mod);
1432 if (sc.explicitVisibility)
1433 imp.visibility = sc.visibility;
1435 if (!imp.aliasId && !imp.names.length) // neither a selective nor a renamed import
1437 ScopeDsymbol scopesym = sc.getScopesym();
1439 if (!imp.isstatic)
1441 scopesym.importScope(imp.mod, imp.visibility);
1445 imp.addPackageAccess(scopesym);
1448 // if a module has errors it means that parsing has failed.
1449 if (!imp.mod.errors)
1450 imp.mod.dsymbolSemantic(null);
1452 if (imp.mod.needmoduleinfo)
1454 //printf("module4 %s because of %s\n", importer.toChars(), imp.mod.toChars());
1455 importer.needmoduleinfo = 1;
1458 sc = sc.push(imp.mod);
1459 sc.visibility = imp.visibility;
1460 for (size_t i = 0; i < imp.aliasdecls.length; i++)
1462 AliasDeclaration ad = imp.aliasdecls[i];
1463 //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), aliases[i].toChars(), names[i].toChars(), ad._scope);
1464 Dsymbol sym = imp.mod.search(imp.loc, imp.names[i], IgnorePrivateImports);
1465 if (sym)
1467 import dmd.access : symbolIsVisible;
1468 if (!symbolIsVisible(sc, sym) && !sym.errors)
1470 .error(imp.loc, "%s `%s` member `%s` is not visible from module `%s`", imp.mod.kind, imp.mod.toPrettyChars,
1471 imp.names[i].toChars(), sc._module.toChars());
1472 sym.errors = true;
1474 ad.dsymbolSemantic(sc);
1475 // If the import declaration is in non-root module,
1476 // analysis of the aliased symbol is deferred.
1477 // Therefore, don't see the ad.aliassym or ad.type here.
1479 else
1481 Dsymbol s = imp.mod.search_correct(imp.names[i]);
1482 // https://issues.dlang.org/show_bug.cgi?id=23908
1483 // Don't suggest symbols from the importer's module
1484 if (s && s.parent != importer)
1485 .error(imp.loc, "%s `%s` import `%s` not found, did you mean %s `%s`?", imp.mod.kind, imp.mod.toPrettyChars, imp.names[i].toChars(), s.kind(), s.toPrettyChars());
1486 else
1487 .error(imp.loc, "%s `%s` import `%s` not found", imp.mod.kind, imp.mod.toPrettyChars, imp.names[i].toChars());
1488 ad.type = Type.terror;
1491 sc = sc.pop();
1494 imp.semanticRun = PASS.semanticdone;
1496 // object self-imports itself, so skip that
1497 // https://issues.dlang.org/show_bug.cgi?id=7547
1498 // don't list pseudo modules __entrypoint.d, __main.d
1499 // https://issues.dlang.org/show_bug.cgi?id=11117
1500 // https://issues.dlang.org/show_bug.cgi?id=11164
1501 if (global.params.moduleDeps.buffer is null || (imp.id == Id.object && sc._module.ident == Id.object) ||
1502 strcmp(sc._module.ident.toChars(), "__main") == 0)
1503 return;
1505 /* The grammar of the file is:
1506 * ImportDeclaration
1507 * ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
1508 * ModuleAliasIdentifier ] "\n"
1510 * BasicImportDeclaration
1511 * ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
1512 * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
1514 * FilePath
1515 * - any string with '(', ')' and '\' escaped with the '\' character
1517 OutBuffer* ob = global.params.moduleDeps.buffer;
1518 Module imod = sc._module;
1519 if (!global.params.moduleDeps.name)
1520 ob.writestring("depsImport ");
1521 ob.writestring(imod.toPrettyChars());
1522 ob.writestring(" (");
1523 escapePath(ob, imod.srcfile.toChars());
1524 ob.writestring(") : ");
1525 // use visibility instead of sc.visibility because it couldn't be
1526 // resolved yet, see the comment above
1527 visibilityToBuffer(*ob, imp.visibility);
1528 ob.writeByte(' ');
1529 if (imp.isstatic)
1531 stcToBuffer(*ob, STC.static_);
1532 ob.writeByte(' ');
1534 ob.writestring(": ");
1535 foreach (pid; imp.packages)
1537 ob.printf("%s.", pid.toChars());
1539 ob.writestring(imp.id.toString());
1540 ob.writestring(" (");
1541 if (imp.mod)
1542 escapePath(ob, imp.mod.srcfile.toChars());
1543 else
1544 ob.writestring("???");
1545 ob.writeByte(')');
1546 foreach (i, name; imp.names)
1548 if (i == 0)
1549 ob.writeByte(':');
1550 else
1551 ob.writeByte(',');
1552 Identifier _alias = imp.aliases[i];
1553 if (!_alias)
1555 ob.printf("%s", name.toChars());
1556 _alias = name;
1558 else
1559 ob.printf("%s=%s", _alias.toChars(), name.toChars());
1561 if (imp.aliasId)
1562 ob.printf(" -> %s", imp.aliasId.toChars());
1563 ob.writenl();
1566 void attribSemantic(AttribDeclaration ad)
1568 if (ad.semanticRun != PASS.initial)
1569 return;
1570 ad.semanticRun = PASS.semantic;
1571 Dsymbols* d = ad.include(sc);
1572 //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
1573 if (d)
1575 Scope* sc2 = ad.newScope(sc);
1576 bool errors;
1577 for (size_t i = 0; i < d.length; i++)
1579 Dsymbol s = (*d)[i];
1580 s.dsymbolSemantic(sc2);
1581 errors |= s.errors;
1583 ad.errors |= errors;
1584 if (sc2 != sc)
1585 sc2.pop();
1587 ad.semanticRun = PASS.semanticdone;
1590 override void visit(AttribDeclaration atd)
1592 attribSemantic(atd);
1595 override void visit(AnonDeclaration scd)
1597 //printf("\tAnonDeclaration::semantic isunion:%d ptr:%p\n", scd.isunion, scd);
1598 assert(sc.parent);
1599 auto p = sc.parent.pastMixin();
1600 auto ad = p.isAggregateDeclaration();
1601 if (!ad)
1603 error(scd.loc, "%s can only be a part of an aggregate, not %s `%s`", scd.kind(), p.kind(), p.toChars());
1604 scd.errors = true;
1605 return;
1608 if (!scd.decl)
1609 return;
1611 sc = sc.push();
1612 sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
1613 sc.inunion = scd.isunion ? scd : null;
1614 sc.flags = 0;
1615 for (size_t i = 0; i < scd.decl.length; i++)
1617 Dsymbol s = (*scd.decl)[i];
1618 if (auto var = s.isVarDeclaration)
1620 if (scd.isunion)
1621 var.overlapped = true;
1623 s.dsymbolSemantic(sc);
1625 sc = sc.pop();
1628 override void visit(PragmaDeclaration pd)
1630 StringExp verifyMangleString(ref Expression e)
1632 auto se = semanticString(sc, e, "mangled name");
1633 if (!se)
1634 return null;
1635 e = se;
1636 if (!se.len)
1638 .error(pd.loc, "%s `%s` - zero-length string not allowed for mangled name", pd.kind, pd.toPrettyChars);
1639 return null;
1641 if (se.sz != 1)
1643 .error(pd.loc, "%s `%s` - mangled name characters can only be of type `char`", pd.kind, pd.toPrettyChars);
1644 return null;
1646 version (all)
1648 /* Note: D language specification should not have any assumption about backend
1649 * implementation. Ideally pragma(mangle) can accept a string of any content.
1651 * Therefore, this validation is compiler implementation specific.
1653 auto slice = se.peekString();
1654 for (size_t i = 0; i < se.len;)
1656 dchar c = slice[i];
1657 if (c < 0x80)
1659 if (c.isValidMangling)
1661 ++i;
1662 continue;
1664 else
1666 .error(pd.loc, "%s `%s` char 0x%02x not allowed in mangled name", pd.kind, pd.toPrettyChars, c);
1667 break;
1670 if (const msg = utf_decodeChar(slice, i, c))
1672 .error(pd.loc, "%s `%s` %.*s", pd.kind, pd.toPrettyChars, cast(int)msg.length, msg.ptr);
1673 break;
1675 if (!isUniAlpha(c))
1677 .error(pd.loc, "%s `%s` char `0x%04x` not allowed in mangled name", pd.kind, pd.toPrettyChars, c);
1678 break;
1682 return se;
1684 void declarations()
1686 if (!pd.decl)
1687 return;
1689 Scope* sc2 = pd.newScope(sc);
1690 scope(exit)
1691 if (sc2 != sc)
1692 sc2.pop();
1694 foreach (s; (*pd.decl)[])
1696 if (pd.ident == Id.printf || pd.ident == Id.scanf)
1698 s.setPragmaPrintf(pd.ident == Id.printf);
1699 s.dsymbolSemantic(sc2);
1700 continue;
1703 s.dsymbolSemantic(sc2);
1704 if (pd.ident != Id.mangle)
1705 continue;
1706 assert(pd.args);
1707 if (auto ad = s.isAggregateDeclaration())
1709 Expression e = (*pd.args)[0];
1710 sc2 = sc2.startCTFE();
1711 e = e.expressionSemantic(sc);
1712 e = resolveProperties(sc2, e);
1713 sc2 = sc2.endCTFE();
1714 AggregateDeclaration agg;
1715 if (auto tc = e.type.isTypeClass())
1716 agg = tc.sym;
1717 else if (auto ts = e.type.isTypeStruct())
1718 agg = ts.sym;
1719 ad.pMangleOverride = new MangleOverride;
1720 void setString(ref Expression e)
1722 if (auto se = verifyMangleString(e))
1724 const name = (cast(const(char)[])se.peekData()).xarraydup;
1725 ad.pMangleOverride.id = Identifier.idPool(name);
1726 e = se;
1728 else
1729 error(e.loc, "must be a string");
1731 if (agg)
1733 ad.pMangleOverride.agg = agg;
1734 if (pd.args.length == 2)
1736 setString((*pd.args)[1]);
1738 else
1739 ad.pMangleOverride.id = agg.ident;
1741 else
1742 setString((*pd.args)[0]);
1744 else if (auto td = s.isTemplateDeclaration())
1746 .error(pd.loc, "%s `%s` cannot apply to a template declaration", pd.kind, pd.toPrettyChars);
1747 errorSupplemental(pd.loc, "use `template Class(Args...){ pragma(mangle, \"other_name\") class Class {} }`");
1749 else if (auto se = verifyMangleString((*pd.args)[0]))
1751 const name = (cast(const(char)[])se.peekData()).xarraydup;
1752 uint cnt = setMangleOverride(s, name);
1753 if (cnt > 1)
1754 .error(pd.loc, "%s `%s` can only apply to a single declaration", pd.kind, pd.toPrettyChars);
1759 void noDeclarations()
1761 if (pd.decl)
1763 .error(pd.loc, "%s `%s` is missing a terminating `;`", pd.kind, pd.toPrettyChars);
1764 declarations();
1765 // do them anyway, to avoid segfaults.
1769 // Should be merged with PragmaStatement
1770 //printf("\tPragmaDeclaration::semantic '%s'\n", pd.toChars());
1771 if (target.supportsLinkerDirective())
1773 if (pd.ident == Id.linkerDirective)
1775 if (!pd.args || pd.args.length != 1)
1776 .error(pd.loc, "%s `%s` one string argument expected for pragma(linkerDirective)", pd.kind, pd.toPrettyChars);
1777 else
1779 auto se = semanticString(sc, (*pd.args)[0], "linker directive");
1780 if (!se)
1781 return noDeclarations();
1782 (*pd.args)[0] = se;
1783 if (global.params.v.verbose)
1784 message("linkopt %.*s", cast(int)se.len, se.peekString().ptr);
1786 return noDeclarations();
1789 if (pd.ident == Id.msg)
1791 if (!pd.args)
1792 return noDeclarations();
1794 if (!pragmaMsgSemantic(pd.loc, sc, pd.args))
1795 return;
1797 return noDeclarations();
1799 else if (pd.ident == Id.lib)
1801 if (!pd.args || pd.args.length != 1)
1802 .error(pd.loc, "%s `%s` string expected for library name", pd.kind, pd.toPrettyChars);
1803 else
1805 auto se = semanticString(sc, (*pd.args)[0], "library name");
1806 if (!se)
1807 return noDeclarations();
1808 (*pd.args)[0] = se;
1810 auto name = se.peekString().xarraydup;
1811 if (global.params.v.verbose)
1812 message("library %s", name.ptr);
1813 if (global.params.moduleDeps.buffer && !global.params.moduleDeps.name)
1815 OutBuffer* ob = global.params.moduleDeps.buffer;
1816 Module imod = sc._module;
1817 ob.writestring("depsLib ");
1818 ob.writestring(imod.toPrettyChars());
1819 ob.writestring(" (");
1820 escapePath(ob, imod.srcfile.toChars());
1821 ob.writestring(") : ");
1822 ob.writestring(name);
1823 ob.writenl();
1825 mem.xfree(name.ptr);
1827 return noDeclarations();
1829 else if (pd.ident == Id.startaddress)
1831 pragmaStartAddressSemantic(pd.loc, sc, pd.args);
1832 return noDeclarations();
1834 else if (pd.ident == Id.Pinline)
1836 // this pragma now gets evaluated on demand in function semantic
1838 return declarations();
1840 else if (pd.ident == Id.mangle)
1842 if (!pd.args)
1843 pd.args = new Expressions();
1844 if (pd.args.length == 0 || pd.args.length > 2)
1846 .error(pd.loc, pd.args.length == 0 ? "%s `%s` - string expected for mangled name"
1847 : "%s `%s` expected 1 or 2 arguments", pd.kind, pd.toPrettyChars);
1848 pd.args.setDim(1);
1849 (*pd.args)[0] = ErrorExp.get(); // error recovery
1851 return declarations();
1853 else if (pd.ident == Id.crt_constructor || pd.ident == Id.crt_destructor)
1855 if (pd.args && pd.args.length != 0)
1856 .error(pd.loc, "%s `%s` takes no argument", pd.kind, pd.toPrettyChars);
1857 else
1859 immutable isCtor = pd.ident == Id.crt_constructor;
1861 static uint recurse(Dsymbol s, bool isCtor)
1863 if (auto ad = s.isAttribDeclaration())
1865 uint nestedCount;
1866 auto decls = ad.include(null);
1867 if (decls)
1869 for (size_t i = 0; i < decls.length; ++i)
1870 nestedCount += recurse((*decls)[i], isCtor);
1872 return nestedCount;
1874 else if (auto f = s.isFuncDeclaration())
1876 if (isCtor)
1877 f.isCrtCtor = true;
1878 else
1879 f.isCrtDtor = true;
1881 return 1;
1883 else
1884 return 0;
1885 assert(0);
1888 if (recurse(pd, isCtor) > 1)
1889 .error(pd.loc, "%s `%s` can only apply to a single declaration", pd.kind, pd.toPrettyChars);
1891 return declarations();
1893 else if (pd.ident == Id.printf || pd.ident == Id.scanf)
1895 if (pd.args && pd.args.length != 0)
1896 .error(pd.loc, "%s `%s` takes no argument", pd.kind, pd.toPrettyChars);
1897 return declarations();
1899 else if (!global.params.ignoreUnsupportedPragmas)
1901 error(pd.loc, "unrecognized `pragma(%s)`", pd.ident.toChars());
1902 return declarations();
1905 if (!global.params.v.verbose)
1906 return declarations();
1908 /* Print unrecognized pragmas
1910 OutBuffer buf;
1911 buf.writestring(pd.ident.toString());
1912 if (pd.args)
1914 const errors_save = global.startGagging();
1915 for (size_t i = 0; i < pd.args.length; i++)
1917 Expression e = (*pd.args)[i];
1918 sc = sc.startCTFE();
1919 e = e.expressionSemantic(sc);
1920 e = resolveProperties(sc, e);
1921 sc = sc.endCTFE();
1922 e = e.ctfeInterpret();
1923 if (i == 0)
1924 buf.writestring(" (");
1925 else
1926 buf.writeByte(',');
1927 buf.writestring(e.toChars());
1929 if (pd.args.length)
1930 buf.writeByte(')');
1931 global.endGagging(errors_save);
1933 message("pragma %s", buf.peekChars());
1934 return declarations();
1937 override void visit(StaticIfDeclaration sid)
1939 attribSemantic(sid);
1942 override void visit(StaticForeachDeclaration sfd)
1944 attribSemantic(sfd);
1947 private Dsymbols* compileIt(MixinDeclaration cd)
1949 //printf("MixinDeclaration::compileIt(loc = %d) %s\n", cd.loc.linnum, cd.exp.toChars());
1950 OutBuffer buf;
1951 if (expressionsToString(buf, sc, cd.exps))
1952 return null;
1954 const errors = global.errors;
1955 const len = buf.length;
1956 buf.writeByte(0);
1957 const str = buf.extractSlice()[0 .. len];
1958 const bool doUnittests = global.params.parsingUnittestsRequired();
1959 auto loc = adjustLocForMixin(str, cd.loc, global.params.mixinOut);
1960 scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
1961 p.transitionIn = global.params.v.vin;
1962 p.nextToken();
1964 auto d = p.parseDeclDefs(0);
1965 if (global.errors != errors)
1966 return null;
1968 if (p.token.value != TOK.endOfFile)
1970 .error(cd.loc, "%s `%s` incomplete mixin declaration `%s`", cd.kind, cd.toPrettyChars, str.ptr);
1971 return null;
1973 return d;
1976 /***********************************************************
1977 * https://dlang.org/spec/module.html#mixin-declaration
1979 override void visit(MixinDeclaration cd)
1981 //printf("MixinDeclaration::semantic()\n");
1982 if (!cd.compiled)
1984 cd.decl = compileIt(cd);
1985 attribAddMember(cd, sc, cd.scopesym);
1986 cd.compiled = true;
1988 if (cd._scope && cd.decl)
1990 for (size_t i = 0; i < cd.decl.length; i++)
1992 Dsymbol s = (*cd.decl)[i];
1993 s.setScope(cd._scope);
1997 attribSemantic(cd);
2000 override void visit(CPPNamespaceDeclaration ns)
2002 Identifier identFromSE (StringExp se)
2004 const sident = se.toStringz();
2005 if (!sident.length || !Identifier.isValidIdentifier(sident))
2007 error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%.*s`",
2008 cast(int)sident.length, sident.ptr);
2009 return null;
2011 else
2012 return Identifier.idPool(sident);
2015 if (ns.ident !is null)
2016 return attribSemantic(ns);
2018 ns.cppnamespace = sc.namespace;
2019 sc = sc.startCTFE();
2020 ns.exp = ns.exp.expressionSemantic(sc);
2021 ns.exp = resolveProperties(sc, ns.exp);
2022 sc = sc.endCTFE();
2023 ns.exp = ns.exp.ctfeInterpret();
2024 // Can be either a tuple of strings or a string itself
2025 if (auto te = ns.exp.isTupleExp())
2027 expandTuples(te.exps);
2028 CPPNamespaceDeclaration current = ns.cppnamespace;
2029 for (size_t d = 0; d < te.exps.length; ++d)
2031 auto exp = (*te.exps)[d];
2032 auto prev = d ? current : ns.cppnamespace;
2033 current = (d + 1) != te.exps.length
2034 ? new CPPNamespaceDeclaration(ns.loc, exp, null)
2035 : ns;
2036 current.exp = exp;
2037 current.cppnamespace = prev;
2038 if (auto se = exp.toStringExp())
2040 current.ident = identFromSE(se);
2041 if (current.ident is null)
2042 return; // An error happened in `identFromSE`
2044 else
2045 error(ns.exp.loc, "`%s`: index %llu is not a string constant, it is a `%s`",
2046 ns.exp.toChars(), cast(ulong) d, ns.exp.type.toChars());
2049 else if (auto se = ns.exp.toStringExp())
2050 ns.ident = identFromSE(se);
2051 // Empty Tuple
2052 else if (ns.exp.isTypeExp() && ns.exp.isTypeExp().type.toBasetype().isTypeTuple())
2055 else if (!ns.exp.type.isTypeError())
2056 error(ns.exp.loc, "compile time string constant (or sequence) expected, not `%s`",
2057 ns.exp.toChars());
2058 attribSemantic(ns);
2061 override void visit(UserAttributeDeclaration uad)
2063 //printf("UserAttributeDeclaration::semantic() %p\n", this);
2064 if (uad.decl && !uad._scope)
2065 uad.Dsymbol.setScope(sc); // for function local symbols
2066 arrayExpressionSemantic(uad.atts.peekSlice(), sc, true);
2067 return attribSemantic(uad);
2070 override void visit(StaticAssert sa)
2072 if (sa.semanticRun < PASS.semanticdone)
2073 sa.semanticRun = PASS.semanticdone;
2076 override void visit(DebugSymbol ds)
2078 //printf("DebugSymbol::semantic() %s\n", toChars());
2079 if (ds.semanticRun < PASS.semanticdone)
2080 ds.semanticRun = PASS.semanticdone;
2083 override void visit(VersionSymbol vs)
2085 if (vs.semanticRun < PASS.semanticdone)
2086 vs.semanticRun = PASS.semanticdone;
2089 override void visit(Package pkg)
2091 if (pkg.semanticRun < PASS.semanticdone)
2092 pkg.semanticRun = PASS.semanticdone;
2095 override void visit(Module m)
2097 if (m.semanticRun != PASS.initial)
2098 return;
2099 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
2100 m.semanticRun = PASS.semantic;
2101 // Note that modules get their own scope, from scratch.
2102 // This is so regardless of where in the syntax a module
2103 // gets imported, it is unaffected by context.
2104 Scope* sc = m._scope; // see if already got one from importAll()
2105 if (!sc)
2107 sc = Scope.createGlobal(m, global.errorSink); // create root scope
2110 //printf("Module = %p, linkage = %d\n", sc.scopesym, sc.linkage);
2111 // Pass 1 semantic routines: do public side of the definition
2112 m.members.foreachDsymbol( (s)
2114 //printf("\tModule('%s'): '%s'.dsymbolSemantic()\n", toChars(), s.toChars());
2115 s.dsymbolSemantic(sc);
2116 m.runDeferredSemantic();
2119 if (m.userAttribDecl)
2121 m.userAttribDecl.dsymbolSemantic(sc);
2123 if (!m._scope)
2125 sc = sc.pop();
2126 sc.pop(); // 2 pops because Scope.createGlobal() created 2
2128 m.semanticRun = PASS.semanticdone;
2129 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
2132 override void visit(EnumDeclaration ed)
2134 //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), ed.toChars());
2135 //printf("EnumDeclaration::semantic() %p %s\n", ed, ed.toChars());
2136 if (ed.semanticRun >= PASS.semanticdone)
2137 return; // semantic() already completed
2138 if (ed.semanticRun == PASS.semantic)
2140 assert(ed.memtype);
2141 error(ed.loc, "circular reference to enum base type `%s`", ed.memtype.toChars());
2142 ed.errors = true;
2143 ed.semanticRun = PASS.semanticdone;
2144 return;
2146 Scope* scx = null;
2147 if (ed._scope)
2149 sc = ed._scope;
2150 scx = ed._scope; // save so we don't make redundant copies
2151 ed._scope = null;
2154 if (!sc)
2155 return;
2157 ed.parent = sc.parent;
2158 ed.type = ed.type.typeSemantic(ed.loc, sc);
2160 ed.visibility = sc.visibility;
2161 if (sc.stc & STC.deprecated_)
2162 ed.isdeprecated = true;
2163 ed.userAttribDecl = sc.userAttribDecl;
2164 ed.cppnamespace = sc.namespace;
2166 ed.semanticRun = PASS.semantic;
2167 UserAttributeDeclaration.checkGNUABITag(ed, sc.linkage);
2168 checkMustUseReserved(ed);
2170 if (!ed.members && !ed.memtype) // enum ident;
2172 ed.semanticRun = PASS.semanticdone;
2173 return;
2176 if (!ed.symtab)
2177 ed.symtab = new DsymbolTable();
2179 /* The separate, and distinct, cases are:
2180 * 1. enum { ... }
2181 * 2. enum : memtype { ... }
2182 * 3. enum ident { ... }
2183 * 4. enum ident : memtype { ... }
2184 * 5. enum ident : memtype;
2185 * 6. enum ident;
2188 if (ed.memtype)
2190 ed.memtype = ed.memtype.typeSemantic(ed.loc, sc);
2192 /* Check to see if memtype is forward referenced
2194 if (auto te = ed.memtype.isTypeEnum())
2196 auto sym = te.toDsymbol(sc).isEnumDeclaration();
2197 // Special enums like __c_[u]long[long] are fine to forward reference
2198 // see https://issues.dlang.org/show_bug.cgi?id=20599
2199 if (!sym.isSpecial() && (!sym.memtype || !sym.members || !sym.symtab || sym._scope))
2201 // memtype is forward referenced, so try again later
2202 deferDsymbolSemantic(ed, scx);
2203 //printf("\tdeferring %s\n", toChars());
2204 ed.semanticRun = PASS.initial;
2205 return;
2207 else
2208 // Ensure that semantic is run to detect. e.g. invalid forward references
2209 sym.dsymbolSemantic(sc);
2211 if (ed.memtype.ty == Tvoid)
2213 .error(ed.loc, "%s `%s` base type must not be `void`", ed.kind, ed.toPrettyChars);
2214 ed.memtype = Type.terror;
2216 if (ed.memtype.ty == Terror)
2218 ed.errors = true;
2219 // poison all the members
2220 ed.members.foreachDsymbol( (s) { s.errors = true; } );
2221 ed.semanticRun = PASS.semanticdone;
2222 return;
2226 if (!ed.members) // enum ident : memtype;
2228 ed.semanticRun = PASS.semanticdone;
2229 return;
2232 if (ed.members.length == 0)
2234 .error(ed.loc, "%s `%s enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars());
2235 ed.errors = true;
2236 ed.semanticRun = PASS.semanticdone;
2237 return;
2240 if (!(sc.flags & SCOPE.Cfile)) // C enum remains incomplete until members are done
2241 ed.semanticRun = PASS.semanticdone;
2243 version (none)
2245 // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
2246 // Deprecated in 2.100
2247 // Make an error in 2.110
2248 if (sc.stc & STC.scope_)
2249 deprecation(ed.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
2252 Scope* sce;
2253 if (ed.isAnonymous())
2254 sce = sc;
2255 else
2257 sce = sc.push(ed);
2258 sce.parent = ed;
2260 sce = sce.startCTFE();
2261 sce.setNoFree(); // needed for getMaxMinValue()
2263 /* Each enum member gets the sce scope
2265 ed.members.foreachDsymbol( (s)
2267 EnumMember em = s.isEnumMember();
2268 if (em)
2269 em._scope = sce;
2272 /* addMember() is not called when the EnumDeclaration appears as a function statement,
2273 * so we have to do what addMember() does and install the enum members in the right symbol
2274 * table
2276 addEnumMembersToSymtab(ed, sc, sc.getScopesym());
2278 if (sc.flags & SCOPE.Cfile)
2280 /* C11 6.7.2.2
2282 Type commonType = ed.memtype;
2283 if (!commonType)
2284 commonType = Type.tint32;
2285 ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
2287 // C11 6.7.2.2-2 value must be representable as an int.
2288 // The sizemask represents all values that int will fit into,
2289 // from 0..uint.max. We want to cover int.min..uint.max.
2290 IntRange ir = IntRange.fromType(commonType);
2292 void emSemantic(EnumMember em, ref ulong nextValue)
2294 static void errorReturn(EnumMember em)
2296 em.value = ErrorExp.get();
2297 em.errors = true;
2298 em.semanticRun = PASS.semanticdone;
2301 em.semanticRun = PASS.semantic;
2302 em.type = commonType;
2303 em._linkage = LINK.c;
2304 em.storage_class |= STC.manifest;
2305 if (em.value)
2307 Expression e = em.value;
2308 assert(e.dyncast() == DYNCAST.expression);
2310 /* To merge the type of e with commonType, add 0 of type commonType
2312 if (!ed.memtype)
2313 e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
2315 e = e.expressionSemantic(sc);
2316 e = resolveProperties(sc, e);
2317 e = e.integralPromotions(sc);
2318 e = e.ctfeInterpret();
2319 if (e.op == EXP.error)
2320 return errorReturn(em);
2321 auto ie = e.isIntegerExp();
2322 if (!ie)
2324 // C11 6.7.2.2-2
2325 .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
2326 return errorReturn(em);
2328 if (ed.memtype && !ir.contains(getIntRange(ie)))
2330 // C11 6.7.2.2-2
2331 .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
2332 return errorReturn(em);
2334 nextValue = ie.toInteger();
2335 if (!ed.memtype)
2336 commonType = e.type;
2337 em.value = new IntegerExp(em.loc, nextValue, commonType);
2339 else
2341 // C11 6.7.2.2-3 add 1 to value of previous enumeration constant
2342 bool first = (em == (*em.ed.members)[0]);
2343 if (!first)
2345 Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
2346 if (nextValue == max.toInteger())
2348 .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
2349 return errorReturn(em);
2351 nextValue += 1;
2353 em.value = new IntegerExp(em.loc, nextValue, commonType);
2355 em.type = commonType;
2356 em.semanticRun = PASS.semanticdone;
2359 ed.members.foreachDsymbol( (s)
2361 if (EnumMember em = s.isEnumMember())
2362 emSemantic(em, nextValue);
2365 if (!ed.memtype)
2367 // cast all members to commonType
2368 ed.members.foreachDsymbol( (s)
2370 if (EnumMember em = s.isEnumMember())
2372 em.type = commonType;
2373 em.value = em.value.castTo(sc, commonType);
2378 ed.memtype = commonType;
2379 ed.semanticRun = PASS.semanticdone;
2380 return;
2383 ed.members.foreachDsymbol( (s)
2385 if (EnumMember em = s.isEnumMember())
2386 em.dsymbolSemantic(em._scope);
2388 //printf("defaultval = %lld\n", defaultval);
2390 //if (defaultval) printf("defaultval: %s %s\n", defaultval.toChars(), defaultval.type.toChars());
2391 //printf("members = %s\n", members.toChars());
2394 override void visit(EnumMember em)
2396 //printf("EnumMember::semantic() %s\n", em.toChars());
2398 void errorReturn()
2400 em.errors = true;
2401 em.semanticRun = PASS.semanticdone;
2404 if (em.errors || em.semanticRun >= PASS.semanticdone)
2405 return;
2406 if (em.semanticRun == PASS.semantic)
2408 .error(em.loc, "%s `%s` circular reference to `enum` member", em.kind, em.toPrettyChars);
2409 return errorReturn();
2411 assert(em.ed);
2413 em.ed.dsymbolSemantic(sc);
2414 if (em.ed.errors)
2415 return errorReturn();
2416 if (em.errors || em.semanticRun >= PASS.semanticdone)
2417 return;
2419 if (em._scope)
2420 sc = em._scope;
2421 if (!sc)
2422 return;
2424 em.semanticRun = PASS.semantic;
2426 em.visibility = em.ed.isAnonymous() ? em.ed.visibility : Visibility(Visibility.Kind.public_);
2427 em._linkage = LINK.d;
2428 em.storage_class |= STC.manifest;
2430 // https://issues.dlang.org/show_bug.cgi?id=9701
2431 if (em.ed.isAnonymous())
2433 if (em.userAttribDecl)
2434 em.userAttribDecl.userAttribDecl = em.ed.userAttribDecl;
2435 else
2436 em.userAttribDecl = em.ed.userAttribDecl;
2439 // Eval UDA in this same scope. Issues 19344, 20835, 21122
2440 if (em.userAttribDecl)
2442 // Set scope but avoid extra sc.uda attachment inside setScope()
2443 auto inneruda = em.userAttribDecl.userAttribDecl;
2444 em.userAttribDecl.setScope(sc);
2445 em.userAttribDecl.userAttribDecl = inneruda;
2446 em.userAttribDecl.dsymbolSemantic(sc);
2449 // The first enum member is special
2450 bool first = (em == (*em.ed.members)[0]);
2452 if (em.origType)
2454 em.origType = em.origType.typeSemantic(em.loc, sc);
2455 em.type = em.origType;
2456 assert(em.value); // "type id;" is not a valid enum member declaration
2459 if (em.value)
2461 Expression e = em.value;
2462 assert(e.dyncast() == DYNCAST.expression);
2463 e = e.expressionSemantic(sc);
2464 e = resolveProperties(sc, e);
2465 e = e.ctfeInterpret();
2466 if (e.op == EXP.error)
2467 return errorReturn();
2468 if (first && !em.ed.memtype && !em.ed.isAnonymous())
2470 em.ed.memtype = e.type;
2471 if (em.ed.memtype.ty == Terror)
2473 em.ed.errors = true;
2474 return errorReturn();
2476 if (em.ed.memtype.ty != Terror)
2478 /* https://issues.dlang.org/show_bug.cgi?id=11746
2479 * All of named enum members should have same type
2480 * with the first member. If the following members were referenced
2481 * during the first member semantic, their types should be unified.
2483 em.ed.members.foreachDsymbol( (s)
2485 EnumMember enm = s.isEnumMember();
2486 if (!enm || enm == em || enm.semanticRun < PASS.semanticdone || enm.origType)
2487 return;
2489 //printf("[%d] em = %s, em.semanticRun = %d\n", i, toChars(), em.semanticRun);
2490 Expression ev = enm.value;
2491 ev = ev.implicitCastTo(sc, em.ed.memtype);
2492 ev = ev.ctfeInterpret();
2493 ev = ev.castTo(sc, em.ed.type);
2494 if (ev.op == EXP.error)
2495 em.ed.errors = true;
2496 enm.value = ev;
2499 if (em.ed.errors)
2501 em.ed.memtype = Type.terror;
2502 return errorReturn();
2507 if (em.ed.memtype && !em.origType)
2509 e = e.implicitCastTo(sc, em.ed.memtype);
2510 e = e.ctfeInterpret();
2512 // save origValue for better json output
2513 em.origValue = e;
2515 if (!em.ed.isAnonymous())
2517 e = e.castTo(sc, em.ed.type.addMod(e.type.mod)); // https://issues.dlang.org/show_bug.cgi?id=12385
2518 e = e.ctfeInterpret();
2521 else if (em.origType)
2523 e = e.implicitCastTo(sc, em.origType);
2524 e = e.ctfeInterpret();
2525 assert(em.ed.isAnonymous());
2527 // save origValue for better json output
2528 em.origValue = e;
2530 em.value = e;
2532 else if (first)
2534 Type t;
2535 if (em.ed.memtype)
2536 t = em.ed.memtype;
2537 else
2539 t = Type.tint32;
2540 if (!em.ed.isAnonymous())
2541 em.ed.memtype = t;
2543 const errors = global.startGagging();
2544 Expression e = new IntegerExp(em.loc, 0, t);
2545 e = e.ctfeInterpret();
2546 if (global.endGagging(errors))
2548 error(em.loc, "cannot generate 0 value of type `%s` for `%s`",
2549 t.toChars(), em.toChars());
2551 // save origValue for better json output
2552 em.origValue = e;
2554 if (!em.ed.isAnonymous())
2556 e = e.castTo(sc, em.ed.type);
2557 e = e.ctfeInterpret();
2559 em.value = e;
2561 else
2563 /* Find the previous enum member,
2564 * and set this to be the previous value + 1
2566 EnumMember emprev = null;
2567 em.ed.members.foreachDsymbol( (s)
2569 if (auto enm = s.isEnumMember())
2571 if (enm == em)
2572 return 1; // found
2573 emprev = enm;
2575 return 0; // continue
2578 assert(emprev);
2579 if (emprev.semanticRun < PASS.semanticdone) // if forward reference
2580 emprev.dsymbolSemantic(emprev._scope); // resolve it
2581 if (emprev.errors)
2582 return errorReturn();
2584 auto errors = global.startGagging();
2585 Expression eprev = emprev.value;
2586 assert(eprev);
2587 // .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645
2588 Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
2589 ? em.ed.memtype
2590 : eprev.type;
2592 https://issues.dlang.org/show_bug.cgi?id=20777
2593 Previously this used getProperty, which doesn't consider anything user defined,
2594 this construct does do that and thus fixes the bug.
2596 Expression emax = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
2597 emax = emax.expressionSemantic(sc);
2598 emax = emax.ctfeInterpret();
2600 // check that (eprev != emax)
2601 Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
2602 e = e.expressionSemantic(sc);
2603 e = e.ctfeInterpret();
2604 if (global.endGagging(errors))
2606 // display an introductory error before showing what actually failed
2607 error(em.loc, "cannot check `%s` value for overflow", em.toPrettyChars());
2608 // rerun to show errors
2609 Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
2610 e2 = e2.expressionSemantic(sc);
2611 e2 = e2.ctfeInterpret();
2612 e2 = new EqualExp(EXP.equal, em.loc, eprev, e2);
2613 e2 = e2.expressionSemantic(sc);
2614 e2 = e2.ctfeInterpret();
2616 // now any errors are for generating a value
2617 if (e.toInteger())
2619 auto mt = em.ed.memtype;
2620 if (!mt)
2621 mt = eprev.type;
2622 .error(em.loc, "%s `%s` initialization with `%s.%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars,
2623 emprev.ed.toChars(), emprev.toChars(), mt.toChars());
2624 return errorReturn();
2626 errors = global.startGagging();
2627 // Now set e to (eprev + 1)
2628 e = new AddExp(em.loc, eprev, IntegerExp.literal!1);
2629 e = e.expressionSemantic(sc);
2630 e = e.castTo(sc, eprev.type);
2631 e = e.ctfeInterpret();
2632 if (global.endGagging(errors))
2634 error(em.loc, "cannot generate value for `%s`", em.toPrettyChars());
2635 // rerun to show errors
2636 Expression e2 = new AddExp(em.loc, eprev, IntegerExp.literal!1);
2637 e2 = e2.expressionSemantic(sc);
2638 e2 = e2.castTo(sc, eprev.type);
2639 e2 = e2.ctfeInterpret();
2641 // save origValue (without cast) for better json output
2642 if (e.op != EXP.error) // avoid duplicate diagnostics
2644 assert(emprev.origValue);
2645 em.origValue = new AddExp(em.loc, emprev.origValue, IntegerExp.literal!1);
2646 em.origValue = em.origValue.expressionSemantic(sc);
2647 em.origValue = em.origValue.ctfeInterpret();
2650 if (e.op == EXP.error)
2651 return errorReturn();
2652 if (e.type.isfloating())
2654 // Check that e != eprev (not always true for floats)
2655 Expression etest = new EqualExp(EXP.equal, em.loc, e, eprev);
2656 etest = etest.expressionSemantic(sc);
2657 etest = etest.ctfeInterpret();
2658 if (etest.toInteger())
2660 .error(em.loc, "%s `%s` has inexact value due to loss of precision", em.kind, em.toPrettyChars);
2661 return errorReturn();
2664 em.value = e;
2666 if (!em.origType)
2667 em.type = em.value.type;
2669 assert(em.origValue);
2670 em.semanticRun = PASS.semanticdone;
2673 override void visit(TemplateDeclaration tempdecl)
2675 static if (LOG)
2677 printf("TemplateDeclaration.dsymbolSemantic(this = %p, id = '%s')\n", this, tempdecl.ident.toChars());
2678 printf("sc.stc = %llx\n", sc.stc);
2679 printf("sc.module = %s\n", sc._module.toChars());
2681 if (tempdecl.semanticRun != PASS.initial)
2682 return; // semantic() already run
2684 if (tempdecl._scope)
2686 sc = tempdecl._scope;
2687 tempdecl._scope = null;
2689 if (!sc)
2690 return;
2692 // Remember templates defined in module object that we need to know about
2693 if (sc._module && sc._module.ident == Id.object)
2695 if (tempdecl.ident == Id.RTInfo)
2696 Type.rtinfo = tempdecl;
2699 /* Remember Scope for later instantiations, but make
2700 * a copy since attributes can change.
2702 if (!tempdecl._scope)
2704 tempdecl._scope = sc.copy();
2705 tempdecl._scope.setNoFree();
2708 tempdecl.semanticRun = PASS.semantic;
2710 tempdecl.parent = sc.parent;
2711 tempdecl.visibility = sc.visibility;
2712 tempdecl.userAttribDecl = sc.userAttribDecl;
2713 tempdecl.cppnamespace = sc.namespace;
2714 tempdecl.isstatic = tempdecl.toParent().isModule() || (tempdecl._scope.stc & STC.static_);
2715 tempdecl.deprecated_ = !!(sc.stc & STC.deprecated_);
2717 UserAttributeDeclaration.checkGNUABITag(tempdecl, sc.linkage);
2719 if (!tempdecl.isstatic)
2721 if (auto ad = tempdecl.parent.pastMixin().isAggregateDeclaration())
2722 ad.makeNested();
2725 // Set up scope for parameters
2726 auto paramsym = new ScopeDsymbol();
2727 paramsym.parent = tempdecl.parent;
2728 Scope* paramscope = sc.push(paramsym);
2729 paramscope.stc = 0;
2731 if (global.params.ddoc.doOutput)
2733 tempdecl.origParameters = new TemplateParameters(tempdecl.parameters.length);
2734 for (size_t i = 0; i < tempdecl.parameters.length; i++)
2736 TemplateParameter tp = (*tempdecl.parameters)[i];
2737 (*tempdecl.origParameters)[i] = tp.syntaxCopy();
2741 for (size_t i = 0; i < tempdecl.parameters.length; i++)
2743 TemplateParameter tp = (*tempdecl.parameters)[i];
2744 if (!tp.declareParameter(paramscope))
2746 error(tp.loc, "parameter `%s` multiply defined", tp.ident.toChars());
2747 tempdecl.errors = true;
2749 if (!tp.tpsemantic(paramscope, tempdecl.parameters))
2751 tempdecl.errors = true;
2753 if (i + 1 != tempdecl.parameters.length && tp.isTemplateTupleParameter())
2755 .error(tempdecl.loc, "%s `%s` template sequence parameter must be the last one", tempdecl.kind, tempdecl.toPrettyChars);
2756 tempdecl.errors = true;
2760 /* Calculate TemplateParameter.dependent
2762 TemplateParameters tparams = TemplateParameters(1);
2763 for (size_t i = 0; i < tempdecl.parameters.length; i++)
2765 TemplateParameter tp = (*tempdecl.parameters)[i];
2766 tparams[0] = tp;
2768 for (size_t j = 0; j < tempdecl.parameters.length; j++)
2770 // Skip cases like: X(T : T)
2771 if (i == j)
2772 continue;
2774 if (TemplateTypeParameter ttp = (*tempdecl.parameters)[j].isTemplateTypeParameter())
2776 if (reliesOnTident(ttp.specType, &tparams))
2777 tp.dependent = true;
2779 else if (TemplateAliasParameter tap = (*tempdecl.parameters)[j].isTemplateAliasParameter())
2781 if (reliesOnTident(tap.specType, &tparams) ||
2782 reliesOnTident(isType(tap.specAlias), &tparams))
2784 tp.dependent = true;
2790 paramscope.pop();
2792 // Compute again
2793 tempdecl.onemember = null;
2794 if (tempdecl.members)
2796 Dsymbol s;
2797 if (Dsymbol.oneMembers(tempdecl.members, &s, tempdecl.ident) && s)
2799 tempdecl.onemember = s;
2800 s.parent = tempdecl;
2804 /* BUG: should check:
2805 * 1. template functions must not introduce virtual functions, as they
2806 * cannot be accomodated in the vtbl[]
2807 * 2. templates cannot introduce non-static data members (i.e. fields)
2808 * as they would change the instance size of the aggregate.
2811 tempdecl.semanticRun = PASS.semanticdone;
2814 override void visit(TemplateInstance ti)
2816 templateInstanceSemantic(ti, sc, ArgumentList());
2819 override void visit(TemplateMixin tm)
2821 static if (LOG)
2823 printf("+TemplateMixin.dsymbolSemantic('%s', this=%p)\n", tm.toChars(), tm);
2824 fflush(stdout);
2826 if (tm.semanticRun != PASS.initial)
2828 // When a class/struct contains mixin members, and is done over
2829 // because of forward references, never reach here so semanticRun
2830 // has been reset to PASS.initial.
2831 static if (LOG)
2833 printf("\tsemantic done\n");
2835 return;
2837 tm.semanticRun = PASS.semantic;
2838 static if (LOG)
2840 printf("\tdo semantic\n");
2843 Scope* scx = null;
2844 if (tm._scope)
2846 sc = tm._scope;
2847 scx = tm._scope; // save so we don't make redundant copies
2848 tm._scope = null;
2851 /* Run semantic on each argument, place results in tiargs[],
2852 * then find best match template with tiargs
2854 if (!tm.findTempDecl(sc) || !tm.semanticTiargs(sc) || !tm.findBestMatch(sc, ArgumentList()))
2856 if (tm.semanticRun == PASS.initial) // forward reference had occurred
2858 //printf("forward reference - deferring\n");
2859 return deferDsymbolSemantic(tm, scx);
2862 tm.inst = tm;
2863 tm.errors = true;
2864 return; // error recovery
2867 auto tempdecl = tm.tempdecl.isTemplateDeclaration();
2868 assert(tempdecl);
2870 if (!tm.ident)
2872 /* Assign scope local unique identifier, as same as lambdas.
2874 const(char)[] s = "__mixin";
2876 if (FuncDeclaration func = sc.parent.isFuncDeclaration())
2878 tm.symtab = func.localsymtab;
2879 if (tm.symtab)
2881 // Inside template constraint, symtab is not set yet.
2882 goto L1;
2885 else
2887 tm.symtab = sc.parent.isScopeDsymbol().symtab;
2889 assert(tm.symtab);
2890 tm.ident = Identifier.generateId(s, tm.symtab.length + 1);
2891 tm.symtab.insert(tm);
2895 tm.inst = tm;
2896 tm.parent = sc.parent;
2898 /* Detect recursive mixin instantiations.
2900 for (Dsymbol s = tm.parent; s; s = s.parent)
2902 //printf("\ts = '%s'\n", s.toChars());
2903 TemplateMixin tmix = s.isTemplateMixin();
2904 if (!tmix || tempdecl != tmix.tempdecl)
2905 continue;
2907 /* Different argument list lengths happen with variadic args
2909 if (tm.tiargs.length != tmix.tiargs.length)
2910 continue;
2912 for (size_t i = 0; i < tm.tiargs.length; i++)
2914 RootObject o = (*tm.tiargs)[i];
2915 Type ta = isType(o);
2916 Expression ea = isExpression(o);
2917 Dsymbol sa = isDsymbol(o);
2918 RootObject tmo = (*tmix.tiargs)[i];
2919 if (ta)
2921 Type tmta = isType(tmo);
2922 if (!tmta)
2923 goto Lcontinue;
2924 if (!ta.equals(tmta))
2925 goto Lcontinue;
2927 else if (ea)
2929 Expression tme = isExpression(tmo);
2930 if (!tme || !ea.equals(tme))
2931 goto Lcontinue;
2933 else if (sa)
2935 Dsymbol tmsa = isDsymbol(tmo);
2936 if (sa != tmsa)
2937 goto Lcontinue;
2939 else
2940 assert(0);
2942 .error(tm.loc, "%s `%s` recursive mixin instantiation", tm.kind, tm.toPrettyChars);
2943 return;
2945 Lcontinue:
2946 continue;
2949 // Copy the syntax trees from the TemplateDeclaration
2950 tm.members = Dsymbol.arraySyntaxCopy(tempdecl.members);
2951 if (!tm.members)
2952 return;
2954 tm.symtab = new DsymbolTable();
2956 sc.getScopesym().importScope(tm, Visibility(Visibility.Kind.public_));
2958 static if (LOG)
2960 printf("\tcreate scope for template parameters '%s'\n", tm.toChars());
2962 Scope* scy = sc.push(tm);
2963 scy.parent = tm;
2965 /* https://issues.dlang.org/show_bug.cgi?id=930
2967 * If the template that is to be mixed in is in the scope of a template
2968 * instance, we have to also declare the type aliases in the new mixin scope.
2970 auto parentInstance = tempdecl.parent ? tempdecl.parent.isTemplateInstance() : null;
2971 if (parentInstance)
2972 parentInstance.declareParameters(scy);
2974 tm.argsym = new ScopeDsymbol();
2975 tm.argsym.parent = scy.parent;
2976 Scope* argscope = scy.push(tm.argsym);
2978 uint errorsave = global.errors;
2980 // Declare each template parameter as an alias for the argument type
2981 tm.declareParameters(argscope);
2983 // Add members to enclosing scope, as well as this scope
2984 tm.members.foreachDsymbol(s => s.addMember(argscope, tm));
2986 // Do semantic() analysis on template instance members
2987 static if (LOG)
2989 printf("\tdo semantic() on template instance members '%s'\n", tm.toChars());
2991 Scope* sc2 = argscope.push(tm);
2992 //size_t deferred_dim = Module.deferred.length;
2994 __gshared int nest;
2995 //printf("%d\n", nest);
2996 if (++nest > global.recursionLimit)
2998 global.gag = 0; // ensure error message gets printed
2999 .error(tm.loc, "%s `%s` recursive expansion", tm.kind, tm.toPrettyChars);
3000 fatal();
3003 tm.members.foreachDsymbol( s => s.setScope(sc2) );
3005 tm.members.foreachDsymbol( s => s.importAll(sc2) );
3007 tm.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
3009 nest--;
3011 /* In DeclDefs scope, TemplateMixin does not have to handle deferred symbols.
3012 * Because the members would already call Module.addDeferredSemantic() for themselves.
3013 * See Struct, Class, Interface, and EnumDeclaration.dsymbolSemantic().
3015 //if (!sc.func && Module.deferred.length > deferred_dim) {}
3017 AggregateDeclaration ad = tm.isMember();
3018 if (sc.func && !ad)
3020 tm.semantic2(sc2);
3021 tm.semantic3(sc2);
3024 // Give additional context info if error occurred during instantiation
3025 if (global.errors != errorsave)
3027 .error(tm.loc, "%s `%s` error instantiating", tm.kind, tm.toPrettyChars);
3028 tm.errors = true;
3031 sc2.pop();
3032 argscope.pop();
3033 scy.pop();
3035 static if (LOG)
3037 printf("-TemplateMixin.dsymbolSemantic('%s', this=%p)\n", tm.toChars(), tm);
3041 override void visit(Nspace ns)
3043 if (ns.semanticRun != PASS.initial)
3044 return;
3045 static if (LOG)
3047 printf("+Nspace::semantic('%s')\n", ns.toChars());
3048 scope(exit) printf("-Nspace::semantic('%s')\n", ns.toChars());
3050 if (ns._scope)
3052 sc = ns._scope;
3053 ns._scope = null;
3055 if (!sc)
3056 return;
3058 bool repopulateMembers = false;
3059 if (ns.identExp)
3061 // resolve the namespace identifier
3062 sc = sc.startCTFE();
3063 Expression resolved = ns.identExp.expressionSemantic(sc);
3064 resolved = resolveProperties(sc, resolved);
3065 sc = sc.endCTFE();
3066 resolved = resolved.ctfeInterpret();
3067 StringExp name = resolved.toStringExp();
3068 TupleExp tup = name ? null : resolved.isTupleExp();
3069 if (!tup && !name)
3071 error(ns.loc, "expected string expression for namespace name, got `%s`", ns.identExp.toChars());
3072 return;
3074 ns.identExp = resolved; // we don't need to keep the old AST around
3075 if (name)
3077 const(char)[] ident = name.toStringz();
3078 if (ident.length == 0 || !Identifier.isValidIdentifier(ident))
3080 error(ns.loc, "expected valid identifier for C++ namespace but got `%.*s`", cast(int)ident.length, ident.ptr);
3081 return;
3083 ns.ident = Identifier.idPool(ident);
3085 else
3087 // create namespace stack from the tuple
3088 Nspace parentns = ns;
3089 foreach (i, exp; *tup.exps)
3091 name = exp.toStringExp();
3092 if (!name)
3094 error(ns.loc, "expected string expression for namespace name, got `%s`", exp.toChars());
3095 return;
3097 const(char)[] ident = name.toStringz();
3098 if (ident.length == 0 || !Identifier.isValidIdentifier(ident))
3100 error(ns.loc, "expected valid identifier for C++ namespace but got `%.*s`", cast(int)ident.length, ident.ptr);
3101 return;
3103 if (i == 0)
3105 ns.ident = Identifier.idPool(ident);
3107 else
3109 // insert the new namespace
3110 Nspace childns = new Nspace(ns.loc, Identifier.idPool(ident), null, parentns.members);
3111 parentns.members = new Dsymbols;
3112 parentns.members.push(childns);
3113 parentns = childns;
3114 repopulateMembers = true;
3120 ns.semanticRun = PASS.semantic;
3121 ns.parent = sc.parent;
3122 // Link does not matter here, if the UDA is present it will error
3123 UserAttributeDeclaration.checkGNUABITag(ns, LINK.cpp);
3125 if (!ns.members)
3127 ns.semanticRun = PASS.semanticdone;
3128 return;
3130 assert(sc);
3131 sc = sc.push(ns);
3132 sc.linkage = LINK.cpp; // note that namespaces imply C++ linkage
3133 sc.parent = ns;
3134 foreach (s; *ns.members)
3136 if (repopulateMembers)
3138 s.addMember(sc, sc.scopesym);
3139 s.setScope(sc);
3141 s.importAll(sc);
3143 foreach (s; *ns.members)
3145 static if (LOG)
3147 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
3149 s.dsymbolSemantic(sc);
3151 sc.pop();
3152 ns.semanticRun = PASS.semanticdone;
3155 void funcDeclarationSemantic(FuncDeclaration funcdecl)
3157 version (none)
3159 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, funcdecl, funcdecl.toPrettyChars(), sc.linkage);
3160 if (funcdecl.isFuncLiteralDeclaration())
3161 printf("\tFuncLiteralDeclaration()\n");
3162 printf("sc.parent = %s, parent = %s\n", sc.parent.toChars(), funcdecl.parent ? funcdecl.parent.toChars() : "");
3163 printf("type: %p, %s\n", funcdecl.type, funcdecl.type.toChars());
3166 if (funcdecl.semanticRun != PASS.initial && funcdecl.isFuncLiteralDeclaration())
3168 /* Member functions that have return types that are
3169 * forward references can have semantic() run more than
3170 * once on them.
3171 * See test\interface2.d, test20
3173 return;
3176 if (funcdecl.semanticRun >= PASS.semanticdone)
3177 return;
3178 assert(funcdecl.semanticRun <= PASS.semantic);
3179 funcdecl.semanticRun = PASS.semantic;
3181 if (funcdecl._scope)
3183 sc = funcdecl._scope;
3184 funcdecl._scope = null;
3187 if (!sc || funcdecl.errors)
3188 return;
3190 funcdecl.cppnamespace = sc.namespace;
3191 funcdecl.parent = sc.parent;
3192 Dsymbol parent = funcdecl.toParent();
3194 funcdecl.foverrides.setDim(0); // reset in case semantic() is being retried for this function
3196 funcdecl.storage_class |= sc.stc & ~STC.ref_;
3197 AggregateDeclaration ad = funcdecl.isThis();
3198 // Don't nest structs b/c of generated methods which should not access the outer scopes.
3199 // https://issues.dlang.org/show_bug.cgi?id=16627
3200 if (ad && !funcdecl.isGenerated())
3202 funcdecl.storage_class |= ad.storage_class & (STC.TYPECTOR | STC.synchronized_);
3203 ad.makeNested();
3205 if (sc.func)
3206 funcdecl.storage_class |= sc.func.storage_class & STC.disable;
3207 // Remove prefix storage classes silently.
3208 if ((funcdecl.storage_class & STC.TYPECTOR) && !(ad || funcdecl.isNested()))
3209 funcdecl.storage_class &= ~STC.TYPECTOR;
3211 //printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal());
3213 if (sc.flags & SCOPE.compile)
3214 funcdecl.skipCodegen = true;
3216 funcdecl._linkage = sc.linkage;
3217 if (sc.flags & SCOPE.Cfile && funcdecl.isFuncLiteralDeclaration())
3218 funcdecl._linkage = LINK.d; // so they are uniquely mangled
3220 if (auto fld = funcdecl.isFuncLiteralDeclaration())
3222 if (fld.treq)
3224 Type treq = fld.treq;
3225 assert(treq.nextOf().ty == Tfunction);
3226 if (treq.ty == Tdelegate)
3227 fld.tok = TOK.delegate_;
3228 else if (treq.isPtrToFunction())
3229 fld.tok = TOK.function_;
3230 else
3231 assert(0);
3232 funcdecl._linkage = treq.nextOf().toTypeFunction().linkage;
3236 // evaluate pragma(inline)
3237 if (auto pragmadecl = sc.inlining)
3238 funcdecl.inlining = evalPragmaInline(pragmadecl.loc, sc, pragmadecl.args);
3240 funcdecl.visibility = sc.visibility;
3241 funcdecl.userAttribDecl = sc.userAttribDecl;
3242 UserAttributeDeclaration.checkGNUABITag(funcdecl, funcdecl._linkage);
3243 checkMustUseReserved(funcdecl);
3245 if (!funcdecl.originalType)
3246 funcdecl.originalType = funcdecl.type.syntaxCopy();
3248 static TypeFunction getFunctionType(FuncDeclaration fd)
3250 if (auto tf = fd.type.isTypeFunction())
3251 return tf;
3253 if (!fd.type.isTypeError())
3255 .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars());
3256 fd.type = Type.terror;
3258 fd.errors = true;
3259 return null;
3262 if (sc.flags & SCOPE.Cfile)
3264 /* C11 allows a function to be declared with a typedef, D does not.
3266 if (auto ti = funcdecl.type.isTypeIdentifier())
3268 auto tj = ti.typeSemantic(funcdecl.loc, sc);
3269 if (auto tjf = tj.isTypeFunction())
3271 /* Copy the type instead of just pointing to it,
3272 * as we don't merge function types
3274 auto tjf2 = new TypeFunction(tjf.parameterList, tjf.next, tjf.linkage);
3275 funcdecl.type = tjf2;
3276 funcdecl.originalType = tjf2;
3281 if (!getFunctionType(funcdecl))
3282 return;
3284 if (!funcdecl.type.deco)
3286 sc = sc.push();
3287 sc.stc |= funcdecl.storage_class & (STC.disable | STC.deprecated_); // forward to function type
3289 TypeFunction tf = funcdecl.type.toTypeFunction();
3290 if (sc.func)
3292 /* If the nesting parent is pure without inference,
3293 * then this function defaults to pure too.
3295 * auto foo() pure {
3296 * auto bar() {} // become a weak purity function
3297 * class C { // nested class
3298 * auto baz() {} // become a weak purity function
3301 * static auto boo() {} // typed as impure
3302 * // Even though, boo cannot call any impure functions.
3303 * // See also Expression::checkPurity().
3306 if (tf.purity == PURE.impure && (funcdecl.isNested() || funcdecl.isThis()))
3308 FuncDeclaration fd = null;
3309 for (Dsymbol p = funcdecl.toParent2(); p; p = p.toParent2())
3311 if (AggregateDeclaration adx = p.isAggregateDeclaration())
3313 if (adx.isNested())
3314 continue;
3315 break;
3317 if ((fd = p.isFuncDeclaration()) !is null)
3318 break;
3321 /* If the parent's purity is inferred, then this function's purity needs
3322 * to be inferred first.
3324 if (fd && fd.isPureBypassingInference() >= PURE.weak && !funcdecl.isInstantiated())
3326 tf.purity = PURE.fwdref; // default to pure
3331 if (tf.isref)
3332 sc.stc |= STC.ref_;
3333 if (tf.isScopeQual)
3334 sc.stc |= STC.scope_;
3335 if (tf.isnothrow)
3336 sc.stc |= STC.nothrow_;
3337 if (tf.isnogc)
3338 sc.stc |= STC.nogc;
3339 if (tf.isproperty)
3340 sc.stc |= STC.property;
3341 if (tf.purity == PURE.fwdref)
3342 sc.stc |= STC.pure_;
3344 if (tf.trust != TRUST.default_)
3346 sc.stc &= ~STC.safeGroup;
3347 if (tf.trust == TRUST.safe)
3348 sc.stc |= STC.safe;
3349 else if (tf.trust == TRUST.system)
3350 sc.stc |= STC.system;
3351 else if (tf.trust == TRUST.trusted)
3352 sc.stc |= STC.trusted;
3355 if (funcdecl.isCtorDeclaration())
3357 tf.isctor = true;
3358 Type tret = ad.handleType();
3359 assert(tret);
3360 tret = tret.addStorageClass(funcdecl.storage_class | sc.stc);
3361 tret = tret.addMod(funcdecl.type.mod);
3362 tf.next = tret;
3363 if (ad.isStructDeclaration())
3364 sc.stc |= STC.ref_;
3367 // 'return' on a non-static class member function implies 'scope' as well
3368 if (ad && ad.isClassDeclaration() && (tf.isreturn || sc.stc & STC.return_) && !(sc.stc & STC.static_))
3369 sc.stc |= STC.scope_;
3371 // If 'this' has no pointers, remove 'scope' as it has no meaning
3372 // Note: this is already covered by semantic of `VarDeclaration` and `TypeFunction`,
3373 // but existing code relies on `hasPointers()` being called here to resolve forward references:
3374 // https://github.com/dlang/dmd/pull/14232#issuecomment-1162906573
3375 if (sc.stc & STC.scope_ && ad && ad.isStructDeclaration() && !ad.type.hasPointers())
3377 sc.stc &= ~STC.scope_;
3378 tf.isScopeQual = false;
3379 if (tf.isreturnscope)
3381 sc.stc &= ~(STC.return_ | STC.returnScope);
3382 tf.isreturn = false;
3383 tf.isreturnscope = false;
3387 sc.linkage = funcdecl._linkage;
3389 if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested()))
3391 import core.bitop : popcnt;
3392 auto mods = MODtoChars(tf.mod);
3393 .error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, mods);
3394 if (tf.next && tf.next.ty != Tvoid && popcnt(tf.mod) == 1)
3395 .errorSupplemental(funcdecl.loc,
3396 "did you mean to use `%s(%s)` as the return type?", mods, tf.next.toChars());
3398 tf.mod = 0; // remove qualifiers
3401 /* Apply const, immutable, wild and shared storage class
3402 * to the function type. Do this before type semantic.
3404 auto stc = funcdecl.storage_class;
3405 if (funcdecl.type.isImmutable())
3406 stc |= STC.immutable_;
3407 if (funcdecl.type.isConst())
3408 stc |= STC.const_;
3409 if (funcdecl.type.isShared() || funcdecl.storage_class & STC.synchronized_)
3410 stc |= STC.shared_;
3411 if (funcdecl.type.isWild())
3412 stc |= STC.wild;
3413 funcdecl.type = funcdecl.type.addSTC(stc);
3415 funcdecl.type = funcdecl.type.typeSemantic(funcdecl.loc, sc);
3416 sc = sc.pop();
3419 auto f = getFunctionType(funcdecl);
3420 if (!f)
3421 return; // funcdecl's type is not a function
3424 // Merge back function attributes into 'originalType'.
3425 // It's used for mangling, ddoc, and json output.
3426 TypeFunction tfo = funcdecl.originalType.toTypeFunction();
3427 tfo.mod = f.mod;
3428 tfo.isScopeQual = f.isScopeQual;
3429 tfo.isreturninferred = f.isreturninferred;
3430 tfo.isscopeinferred = f.isscopeinferred;
3431 tfo.isref = f.isref;
3432 tfo.isnothrow = f.isnothrow;
3433 tfo.isnogc = f.isnogc;
3434 tfo.isproperty = f.isproperty;
3435 tfo.purity = f.purity;
3436 tfo.trust = f.trust;
3438 funcdecl.storage_class &= ~(STC.TYPECTOR | STC.FUNCATTR);
3441 // check pragma(crt_constructor) signature
3442 if (funcdecl.isCrtCtor || funcdecl.isCrtDtor)
3444 const idStr = funcdecl.isCrtCtor ? "crt_constructor" : "crt_destructor";
3445 if (f.nextOf().ty != Tvoid)
3446 .error(funcdecl.loc, "%s `%s` must return `void` for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
3447 if (funcdecl._linkage != LINK.c && f.parameterList.length != 0)
3448 .error(funcdecl.loc, "%s `%s` must be `extern(C)` for `pragma(%s)` when taking parameters", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
3449 if (funcdecl.isThis())
3450 .error(funcdecl.loc, "%s `%s` cannot be a non-static member function for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
3453 if (funcdecl.overnext && funcdecl.isCsymbol())
3455 /* C does not allow function overloading, but it does allow
3456 * redeclarations of the same function. If .overnext points
3457 * to a redeclaration, ok. Error if it is an overload.
3459 auto fnext = funcdecl.overnext.isFuncDeclaration();
3460 funcDeclarationSemantic(fnext);
3461 auto fn = fnext.type.isTypeFunction();
3462 if (!fn || !cFuncEquivalence(f, fn))
3464 .error(funcdecl.loc, "%s `%s` redeclaration with different type", funcdecl.kind, funcdecl.toPrettyChars);
3465 //printf("t1: %s\n", f.toChars());
3466 //printf("t2: %s\n", fn.toChars());
3468 funcdecl.overnext = null; // don't overload the redeclarations
3471 if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
3472 .error(funcdecl.loc, "%s `%s` storage class `auto` has no effect if return type is not inferred", funcdecl.kind, funcdecl.toPrettyChars);
3474 if (f.isreturn && !funcdecl.needThis() && !funcdecl.isNested())
3476 /* Non-static nested functions have a hidden 'this' pointer to which
3477 * the 'return' applies
3479 if (sc.scopesym && sc.scopesym.isAggregateDeclaration())
3480 .error(funcdecl.loc, "%s `%s` `static` member has no `this` to which `return` can apply", funcdecl.kind, funcdecl.toPrettyChars);
3481 else
3482 error(funcdecl.loc, "top-level function `%s` has no `this` to which `return` can apply", funcdecl.toChars());
3485 if (funcdecl.isAbstract() && !funcdecl.isVirtual())
3487 const(char)* sfunc;
3488 if (funcdecl.isStatic())
3489 sfunc = "static";
3490 else if (funcdecl.visibility.kind == Visibility.Kind.private_ || funcdecl.visibility.kind == Visibility.Kind.package_)
3491 sfunc = visibilityToChars(funcdecl.visibility.kind);
3492 else
3493 sfunc = "final";
3494 .error(funcdecl.loc, "%s `%s` `%s` functions cannot be `abstract`", funcdecl.kind, funcdecl.toPrettyChars, sfunc);
3497 if (funcdecl.isOverride() && !funcdecl.isVirtual() && !funcdecl.isFuncLiteralDeclaration())
3499 Visibility.Kind kind = funcdecl.visible().kind;
3500 if ((kind == Visibility.Kind.private_ || kind == Visibility.Kind.package_) && funcdecl.isMember())
3501 .error(funcdecl.loc, "%s `%s` `%s` method is not virtual and cannot override", funcdecl.kind, funcdecl.toPrettyChars, visibilityToChars(kind));
3502 else
3503 .error(funcdecl.loc, "%s `%s` cannot override a non-virtual function", funcdecl.kind, funcdecl.toPrettyChars);
3506 if (funcdecl.isAbstract() && funcdecl.isFinalFunc())
3507 .error(funcdecl.loc, "%s `%s` cannot be both `final` and `abstract`", funcdecl.kind, funcdecl.toPrettyChars);
3509 if (funcdecl.printf || funcdecl.scanf)
3511 checkPrintfScanfSignature(funcdecl, f, sc);
3514 if (auto id = parent.isInterfaceDeclaration())
3516 funcdecl.storage_class |= STC.abstract_;
3517 if (funcdecl.isCtorDeclaration() || funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration() || funcdecl.isNewDeclaration() || funcdecl.isDelete())
3518 .error(funcdecl.loc, "%s `%s` constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
3519 if (funcdecl.fbody && funcdecl.isVirtual())
3520 .error(funcdecl.loc, "%s `%s` function body only allowed in `final` functions in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
3523 if (UnionDeclaration ud = parent.isUnionDeclaration())
3525 if (funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration())
3526 .error(funcdecl.loc, "%s `%s` destructors, postblits and invariants are not allowed in union `%s`", funcdecl.kind, funcdecl.toPrettyChars, ud.toChars());
3529 if (StructDeclaration sd = parent.isStructDeclaration())
3531 if (funcdecl.isCtorDeclaration())
3533 goto Ldone;
3537 if (ClassDeclaration cd = parent.isClassDeclaration())
3539 parent = cd = objc.getParent(funcdecl, cd);
3541 if (funcdecl.isCtorDeclaration())
3543 goto Ldone;
3546 if (funcdecl.storage_class & STC.abstract_)
3547 cd.isabstract = ThreeState.yes;
3549 // if static function, do not put in vtbl[]
3550 if (!funcdecl.isVirtual())
3552 //printf("\tnot virtual\n");
3553 goto Ldone;
3555 // Suppress further errors if the return type is an error
3556 if (funcdecl.type.nextOf() == Type.terror)
3557 goto Ldone;
3559 bool may_override = false;
3560 for (size_t i = 0; i < cd.baseclasses.length; i++)
3562 BaseClass* b = (*cd.baseclasses)[i];
3563 ClassDeclaration cbd = b.type.toBasetype().isClassHandle();
3564 if (!cbd)
3565 continue;
3566 for (size_t j = 0; j < cbd.vtbl.length; j++)
3568 FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration();
3569 if (!f2 || f2.ident != funcdecl.ident)
3570 continue;
3571 if (cbd.parent && cbd.parent.isTemplateInstance())
3573 if (!f2.functionSemantic())
3574 goto Ldone;
3576 may_override = true;
3579 if (may_override && funcdecl.type.nextOf() is null)
3581 /* If same name function exists in base class but 'this' is auto return,
3582 * cannot find index of base class's vtbl[] to override.
3584 .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars);
3587 /* Find index of existing function in base class's vtbl[] to override
3588 * (the index will be the same as in cd's current vtbl[])
3590 int vi = cd.baseClass ? funcdecl.findVtblIndex(&cd.baseClass.vtbl, cast(int)cd.baseClass.vtbl.length) : -1;
3592 bool doesoverride = false;
3593 switch (vi)
3595 case -1:
3596 Lintro:
3597 /* Didn't find one, so
3598 * This is an 'introducing' function which gets a new
3599 * slot in the vtbl[].
3602 // Verify this doesn't override previous final function
3603 if (cd.baseClass)
3605 Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident);
3606 if (s)
3608 if (auto f2 = s.isFuncDeclaration())
3610 f2 = f2.overloadExactMatch(funcdecl.type);
3611 if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
3612 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars());
3617 /* These quirky conditions mimic what happens when virtual
3618 inheritance is implemented by producing a virtual base table
3619 with offsets to each of the virtual bases.
3621 if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
3622 cd.baseClass && cd.baseClass.vtbl.length)
3624 /* if overriding an interface function, then this is not
3625 * introducing and don't put it in the class vtbl[]
3627 funcdecl.interfaceVirtual = funcdecl.overrideInterface();
3628 if (funcdecl.interfaceVirtual)
3630 //printf("\tinterface function %s\n", toChars());
3631 cd.vtblFinal.push(funcdecl);
3632 goto Linterfaces;
3636 if (funcdecl.isFinalFunc())
3638 // Don't check here, as it may override an interface function
3639 //if (isOverride())
3640 // error("is marked as override, but does not override any function");
3641 cd.vtblFinal.push(funcdecl);
3643 else
3645 //printf("\tintroducing function %s\n", funcdecl.toChars());
3646 funcdecl.isIntroducing = true;
3647 if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads)
3649 /* Overloaded functions with same name are grouped and in reverse order.
3650 * Search for first function of overload group, and insert
3651 * funcdecl into vtbl[] immediately before it.
3653 funcdecl.vtblIndex = cast(int)cd.vtbl.length;
3654 bool found;
3655 foreach (const i, s; cd.vtbl)
3657 if (found)
3658 // the rest get shifted forward
3659 ++s.isFuncDeclaration().vtblIndex;
3660 else if (s.ident == funcdecl.ident && s.parent == parent)
3662 // found first function of overload group
3663 funcdecl.vtblIndex = cast(int)i;
3664 found = true;
3665 ++s.isFuncDeclaration().vtblIndex;
3668 cd.vtbl.insert(funcdecl.vtblIndex, funcdecl);
3670 debug foreach (const i, s; cd.vtbl)
3672 // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl),
3673 // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception.
3674 if (auto fd = s.isFuncDeclaration())
3675 assert(fd.vtblIndex == i ||
3676 (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration) ||
3677 funcdecl.parent.isInterfaceDeclaration); // interface functions can be in multiple vtbls
3680 else
3682 // Append to end of vtbl[]
3683 vi = cast(int)cd.vtbl.length;
3684 cd.vtbl.push(funcdecl);
3685 funcdecl.vtblIndex = vi;
3688 break;
3690 case -2:
3691 // can't determine because of forward references
3692 funcdecl.errors = true;
3693 return;
3695 default:
3697 if (vi >= cd.vtbl.length)
3699 /* the derived class cd doesn't have its vtbl[] allocated yet.
3700 * https://issues.dlang.org/show_bug.cgi?id=21008
3702 .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
3703 funcdecl.errors = true;
3704 return;
3706 FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration();
3707 FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration();
3708 // This function is covariant with fdv
3710 if (fdc == funcdecl)
3712 doesoverride = true;
3713 break;
3716 auto vtf = getFunctionType(fdv);
3717 if (vtf.trust > TRUST.system && f.trust == TRUST.system)
3718 .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars,
3719 fdv.toPrettyChars);
3721 if (fdc.toParent() == parent)
3723 //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
3724 // vi, this, this.toChars(), this.type.toChars(), this.loc.toChars(),
3725 // fdc, fdc .toChars(), fdc .type.toChars(), fdc .loc.toChars(),
3726 // fdv, fdv .toChars(), fdv .type.toChars(), fdv .loc.toChars());
3728 // fdc overrides fdv exactly, then this introduces new function.
3729 if (fdc.type.mod == fdv.type.mod && funcdecl.type.mod != fdv.type.mod)
3730 goto Lintro;
3733 if (fdv.isDeprecated && !funcdecl.isDeprecated)
3734 deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`",
3735 funcdecl.toPrettyChars, fdv.toPrettyChars);
3737 // This function overrides fdv
3738 if (fdv.isFinalFunc())
3739 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars());
3741 if (!funcdecl.isOverride())
3743 if (fdv.isFuture())
3745 deprecation(funcdecl.loc, "`@__future` base class method `%s` is being overridden by `%s`; rename the latter", fdv.toPrettyChars(), funcdecl.toPrettyChars());
3746 // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
3747 goto Lintro;
3749 else
3751 // https://issues.dlang.org/show_bug.cgi?id=17349
3752 error(funcdecl.loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
3753 fdv.toPrettyChars(), funcdecl.toPrettyChars());
3756 doesoverride = true;
3757 if (fdc.toParent() == parent)
3759 // If both are mixins, or both are not, then error.
3760 // If either is not, the one that is not overrides the other.
3761 bool thismixin = funcdecl.parent.isClassDeclaration() !is null;
3762 bool fdcmixin = fdc.parent.isClassDeclaration() !is null;
3763 if (thismixin == fdcmixin)
3765 .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars);
3768 * https://issues.dlang.org/show_bug.cgi?id=711
3770 * If an overriding method is introduced through a mixin,
3771 * we need to update the vtbl so that both methods are
3772 * present.
3774 else if (thismixin)
3776 /* if the mixin introduced the overriding method, then reintroduce it
3777 * in the vtbl. The initial entry for the mixined method
3778 * will be updated at the end of the enclosing `if` block
3779 * to point to the current (non-mixined) function.
3781 auto vitmp = cast(int)cd.vtbl.length;
3782 cd.vtbl.push(fdc);
3783 fdc.vtblIndex = vitmp;
3785 else if (fdcmixin)
3787 /* if the current overriding function is coming from a
3788 * mixined block, then push the current function in the
3789 * vtbl, but keep the previous (non-mixined) function as
3790 * the overriding one.
3792 auto vitmp = cast(int)cd.vtbl.length;
3793 cd.vtbl.push(funcdecl);
3794 funcdecl.vtblIndex = vitmp;
3795 break;
3797 else // fdc overrides fdv
3799 // this doesn't override any function
3800 break;
3803 cd.vtbl[vi] = funcdecl;
3804 funcdecl.vtblIndex = vi;
3806 /* Remember which functions this overrides
3808 funcdecl.foverrides.push(fdv);
3810 /* This works by whenever this function is called,
3811 * it actually returns tintro, which gets dynamically
3812 * cast to type. But we know that tintro is a base
3813 * of type, so we could optimize it by not doing a
3814 * dynamic cast, but just subtracting the isBaseOf()
3815 * offset if the value is != null.
3818 if (fdv.tintro)
3819 funcdecl.tintro = fdv.tintro;
3820 else if (!funcdecl.type.equals(fdv.type))
3822 auto tnext = funcdecl.type.nextOf();
3823 if (auto handle = tnext.isClassHandle())
3825 if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
3826 handle.dsymbolSemantic(null);
3828 /* Only need to have a tintro if the vptr
3829 * offsets differ
3831 int offset;
3832 if (fdv.type.nextOf().isBaseOf(tnext, &offset))
3834 funcdecl.tintro = fdv.type;
3837 break;
3841 /* Go through all the interface bases.
3842 * If this function is covariant with any members of those interface
3843 * functions, set the tintro.
3845 Linterfaces:
3846 bool foundVtblMatch = false;
3848 for (ClassDeclaration bcd = cd; !foundVtblMatch && bcd; bcd = bcd.baseClass)
3850 foreach (b; bcd.interfaces)
3852 vi = funcdecl.findVtblIndex(&b.sym.vtbl, cast(int)b.sym.vtbl.length);
3853 switch (vi)
3855 case -1:
3856 break;
3858 case -2:
3859 // can't determine because of forward references
3860 funcdecl.errors = true;
3861 return;
3863 default:
3865 auto fdv = cast(FuncDeclaration)b.sym.vtbl[vi];
3866 Type ti = null;
3868 foundVtblMatch = true;
3870 /* Remember which functions this overrides
3872 funcdecl.foverrides.push(fdv);
3874 if (fdv.tintro)
3875 ti = fdv.tintro;
3876 else if (!funcdecl.type.equals(fdv.type))
3878 /* Only need to have a tintro if the vptr
3879 * offsets differ
3881 int offset;
3882 if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset))
3884 ti = fdv.type;
3887 if (ti)
3889 if (funcdecl.tintro)
3891 if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null))
3893 .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars());
3896 else
3898 funcdecl.tintro = ti;
3905 if (foundVtblMatch)
3907 goto L2;
3910 if (!doesoverride && funcdecl.isOverride() && (funcdecl.type.nextOf() || !may_override))
3912 BaseClass* bc = null;
3913 Dsymbol s = null;
3914 for (size_t i = 0; i < cd.baseclasses.length; i++)
3916 bc = (*cd.baseclasses)[i];
3917 s = bc.sym.search_correct(funcdecl.ident);
3918 if (s)
3919 break;
3922 if (s)
3924 HdrGenState hgs;
3925 OutBuffer buf;
3927 auto fd = s.isFuncDeclaration();
3928 functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf,
3929 new Identifier(funcdecl.toPrettyChars()), &hgs, null);
3930 const(char)* funcdeclToChars = buf.peekChars();
3932 if (fd)
3934 OutBuffer buf1;
3936 if (fd.ident == funcdecl.ident)
3937 hgs.fullQual = true;
3939 // https://issues.dlang.org/show_bug.cgi?id=23745
3940 // If the potentially overridden function contains errors,
3941 // inform the user to fix that one first
3942 if (fd.errors)
3944 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
3945 funcdecl.toChars(), fd.toPrettyChars());
3946 errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden",
3947 fd.toPrettyChars());
3949 else
3951 functionToBufferFull(cast(TypeFunction)(fd.type), buf1,
3952 new Identifier(fd.toPrettyChars()), &hgs, null);
3954 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
3955 funcdeclToChars, buf1.peekChars());
3958 else
3960 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?",
3961 funcdeclToChars, s.kind, s.toPrettyChars());
3962 errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden");
3965 else
3966 .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars);
3970 objc.setSelector(funcdecl, sc);
3971 objc.checkLinkage(funcdecl);
3972 objc.addToClassMethodList(funcdecl, cd);
3973 objc.setAsOptional(funcdecl, sc);
3975 /* Go through all the interface bases.
3976 * Disallow overriding any final functions in the interface(s).
3978 foreach (b; cd.interfaces)
3980 if (b.sym)
3982 if (auto s = search_function(b.sym, funcdecl.ident))
3984 if (auto f2 = s.isFuncDeclaration())
3986 f2 = f2.overloadExactMatch(funcdecl.type);
3987 if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
3988 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars());
3994 if (funcdecl.isOverride)
3996 if (funcdecl.storage_class & STC.disable)
3997 deprecation(funcdecl.loc,
3998 "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class",
3999 funcdecl.toPrettyChars);
4001 if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated))
4002 deprecation(funcdecl.loc,
4003 "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class",
4004 funcdecl.toPrettyChars);
4008 else if (funcdecl.isOverride() && !parent.isTemplateInstance())
4009 .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars);
4011 if (auto ti = parent.isTemplateInstance)
4013 objc.setSelector(funcdecl, sc);
4014 objc.setAsOptional(funcdecl, sc);
4017 objc.validateSelector(funcdecl);
4018 objc.validateOptional(funcdecl);
4019 // Reflect this.type to f because it could be changed by findVtblIndex
4020 f = funcdecl.type.toTypeFunction();
4022 Ldone:
4023 if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody())
4024 .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars);
4026 /* Do not allow template instances to add virtual functions
4027 * to a class.
4029 if (funcdecl.isVirtual())
4031 if (auto ti = parent.isTemplateInstance())
4033 // Take care of nested templates
4034 while (1)
4036 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
4037 if (!ti2)
4038 break;
4039 ti = ti2;
4042 // If it's a member template
4043 ClassDeclaration cd = ti.tempdecl.isClassMember();
4044 if (cd)
4046 .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
4051 funcdecl.checkMain(); // Check main() parameters and return type
4053 /* Purity and safety can be inferred for some functions by examining
4054 * the function body.
4056 if (funcdecl.canInferAttributes(sc))
4057 funcdecl.initInferAttributes();
4059 funcdecl.semanticRun = PASS.semanticdone;
4061 /* Save scope for possible later use (if we need the
4062 * function internals)
4064 funcdecl._scope = sc.copy();
4065 funcdecl._scope.setNoFree();
4067 __gshared bool printedMain = false; // semantic might run more than once
4068 if (global.params.v.verbose && !printedMain)
4070 const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null;
4071 Module mod = sc._module;
4073 if (type && mod)
4075 printedMain = true;
4076 auto name = mod.srcfile.toChars();
4077 auto path = FileName.searchPath(global.path, name, true);
4078 message("entry %-10s\t%s", type, path ? path : name);
4082 if (funcdecl.fbody && sc._module.isRoot() &&
4083 (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain()))
4084 global.hasMainFunction = true;
4086 if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot())
4088 // check if `_d_cmain` is defined
4089 bool cmainTemplateExists()
4091 auto rootSymbol = sc.search(funcdecl.loc, Id.empty, null);
4092 if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object))
4093 if (moduleSymbol.search(funcdecl.loc, Id.CMain))
4094 return true;
4096 return false;
4099 // Only mixin `_d_cmain` if it is defined
4100 if (cmainTemplateExists())
4102 // add `mixin _d_cmain!();` to the declaring module
4103 auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain);
4104 auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null);
4105 sc._module.members.push(tm);
4109 assert(funcdecl.type.ty != Terror || funcdecl.errors);
4111 // semantic for parameters' UDAs
4112 foreach (i, param; f.parameterList)
4114 if (param && param.userAttribDecl)
4115 param.userAttribDecl.dsymbolSemantic(sc);
4119 /// Do the semantic analysis on the external interface to the function.
4120 override void visit(FuncDeclaration funcdecl)
4122 funcDeclarationSemantic(funcdecl);
4125 override void visit(CtorDeclaration ctd)
4127 //printf("CtorDeclaration::semantic() %s\n", toChars());
4128 if (ctd.semanticRun >= PASS.semanticdone)
4129 return;
4130 if (ctd._scope)
4132 sc = ctd._scope;
4133 ctd._scope = null;
4136 ctd.parent = sc.parent;
4137 Dsymbol p = ctd.toParentDecl();
4138 AggregateDeclaration ad = p.isAggregateDeclaration();
4139 if (!ad)
4141 error(ctd.loc, "constructor can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
4142 ctd.type = Type.terror;
4143 ctd.errors = true;
4144 return;
4147 sc = sc.push();
4149 if (sc.stc & STC.static_)
4151 if (sc.stc & STC.shared_)
4152 error(ctd.loc, "`shared static` has no effect on a constructor inside a `shared static` block. Use `shared static this()`");
4153 else
4154 error(ctd.loc, "`static` has no effect on a constructor inside a `static` block. Use `static this()`");
4157 sc.stc &= ~STC.static_; // not a static constructor
4159 funcDeclarationSemantic(ctd);
4161 sc.pop();
4163 if (ctd.errors)
4164 return;
4166 TypeFunction tf = ctd.type.toTypeFunction();
4167 immutable dim = tf.parameterList.length;
4168 auto sd = ad.isStructDeclaration();
4170 /* See if it's the default constructor
4171 * But, template constructor should not become a default constructor.
4173 if (ad && (!ctd.parent.isTemplateInstance() || ctd.parent.isTemplateMixin()))
4175 if (!sd)
4177 if (dim == 0 && tf.parameterList.varargs == VarArg.none)
4178 ad.defaultCtor = ctd;
4179 return;
4182 if (dim == 0 && tf.parameterList.varargs == VarArg.none) // empty default ctor w/o any varargs
4184 if (ctd.fbody || !(ctd.storage_class & STC.disable))
4186 .error(ctd.loc, "%s `%s` default constructor for structs only allowed " ~
4187 "with `@disable`, no body, and no parameters", ctd.kind, ctd.toPrettyChars);
4188 ctd.storage_class |= STC.disable;
4189 ctd.fbody = null;
4191 sd.noDefaultCtor = true;
4193 else if (dim == 0 && tf.parameterList.varargs != VarArg.none) // allow varargs only ctor
4196 else if (dim && !tf.parameterList.hasArgsWithoutDefault)
4198 if (ctd.storage_class & STC.disable)
4200 .error(ctd.loc, "%s `%s` is marked `@disable`, so it cannot have default "~
4201 "arguments for all parameters.", ctd.kind, ctd.toPrettyChars);
4202 errorSupplemental(ctd.loc, "Use `@disable this();` if you want to disable default initialization.");
4204 else
4205 .error(ctd.loc, "%s `%s` all parameters have default arguments, "~
4206 "but structs cannot have default constructors.", ctd.kind, ctd.toPrettyChars);
4208 else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
4210 //printf("tf: %s\n", tf.toChars());
4211 auto param = tf.parameterList[0];
4212 if (param.storageClass & STC.ref_ && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
4214 //printf("copy constructor\n");
4215 ctd.isCpCtor = true;
4219 // https://issues.dlang.org/show_bug.cgi?id=22593
4220 else if (auto ti = ctd.parent.isTemplateInstance())
4222 checkHasBothRvalueAndCpCtor(sd, ctd, ti);
4226 override void visit(PostBlitDeclaration pbd)
4228 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
4229 //printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor);
4230 //printf("stc = x%llx\n", sc.stc);
4231 if (pbd.semanticRun >= PASS.semanticdone)
4232 return;
4233 if (pbd._scope)
4235 sc = pbd._scope;
4236 pbd._scope = null;
4239 pbd.parent = sc.parent;
4240 Dsymbol p = pbd.toParent2();
4241 StructDeclaration ad = p.isStructDeclaration();
4242 if (!ad)
4244 error(pbd.loc, "postblit can only be a member of struct, not %s `%s`", p.kind(), p.toChars());
4245 pbd.type = Type.terror;
4246 pbd.errors = true;
4247 return;
4249 if (pbd.ident == Id.postblit && pbd.semanticRun < PASS.semantic)
4250 ad.postblits.push(pbd);
4251 if (!pbd.type)
4252 pbd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, pbd.storage_class);
4254 sc = sc.push();
4255 sc.stc &= ~STC.static_; // not static
4256 sc.linkage = LINK.d;
4258 funcDeclarationSemantic(pbd);
4260 sc.pop();
4263 override void visit(DtorDeclaration dd)
4265 //printf("DtorDeclaration::semantic() %s\n", dd.toChars());
4266 //printf("ident: %s, %s, %p, %p\n", dd.ident.toChars(), Id.dtor.toChars(), dd.ident, Id.dtor);
4267 if (dd.semanticRun >= PASS.semanticdone)
4268 return;
4269 if (dd._scope)
4271 sc = dd._scope;
4272 dd._scope = null;
4275 dd.parent = sc.parent;
4276 Dsymbol p = dd.toParent2();
4277 AggregateDeclaration ad = p.isAggregateDeclaration();
4278 if (!ad)
4280 error(dd.loc, "destructor can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
4281 dd.type = Type.terror;
4282 dd.errors = true;
4283 return;
4286 if (ad.isClassDeclaration() && ad.classKind == ClassKind.d)
4288 // Class destructors are implicitly `scope`
4289 dd.storage_class |= STC.scope_;
4292 if (dd.ident == Id.dtor && dd.semanticRun < PASS.semantic)
4293 ad.userDtors.push(dd);
4294 if (!dd.type)
4296 dd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, dd.storage_class);
4297 if (ad.classKind == ClassKind.cpp && dd.ident == Id.dtor)
4299 if (auto cldec = ad.isClassDeclaration())
4301 assert (cldec.cppDtorVtblIndex == -1); // double-call check already by dd.type
4302 if (cldec.baseClass && cldec.baseClass.cppDtorVtblIndex != -1)
4304 // override the base virtual
4305 cldec.cppDtorVtblIndex = cldec.baseClass.cppDtorVtblIndex;
4307 else if (!dd.isFinal())
4309 // reserve the dtor slot for the destructor (which we'll create later)
4310 cldec.cppDtorVtblIndex = cast(int)cldec.vtbl.length;
4311 cldec.vtbl.push(dd);
4312 if (target.cpp.twoDtorInVtable)
4313 cldec.vtbl.push(dd); // deleting destructor uses a second slot
4319 sc = sc.push();
4320 sc.stc &= ~STC.static_; // not a static destructor
4321 if (sc.linkage != LINK.cpp)
4322 sc.linkage = LINK.d;
4324 funcDeclarationSemantic(dd);
4326 sc.pop();
4329 override void visit(StaticCtorDeclaration scd)
4331 //printf("StaticCtorDeclaration::semantic()\n");
4332 if (scd.semanticRun >= PASS.semanticdone)
4333 return;
4334 if (scd._scope)
4336 sc = scd._scope;
4337 scd._scope = null;
4340 scd.parent = sc.parent;
4341 Dsymbol p = scd.parent.pastMixin();
4342 if (!p.isScopeDsymbol())
4344 const(char)* s = (scd.isSharedStaticCtorDeclaration() ? "shared " : "");
4345 error(scd.loc, "`%sstatic` constructor can only be member of module/aggregate/template, not %s `%s`", s, p.kind(), p.toChars());
4346 scd.type = Type.terror;
4347 scd.errors = true;
4348 return;
4350 if (!scd.type)
4351 scd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, scd.storage_class);
4353 /* If the static ctor appears within a template instantiation,
4354 * it could get called multiple times by the module constructors
4355 * for different modules. Thus, protect it with a gate.
4357 if (scd.isInstantiated() && scd.semanticRun < PASS.semantic)
4359 /* Add this prefix to the constructor:
4360 * ```
4361 * static int gate;
4362 * if (++gate != 1) return;
4363 * ```
4364 * or, for shared constructor:
4365 * ```
4366 * shared int gate;
4367 * if (core.atomic.atomicOp!"+="(gate, 1) != 1) return;
4368 * ```
4370 const bool isShared = !!scd.isSharedStaticCtorDeclaration();
4371 auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
4372 v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
4374 auto sa = new Statements();
4375 Statement s = new ExpStatement(Loc.initial, v);
4376 sa.push(s);
4378 Expression e;
4379 if (isShared)
4381 e = doAtomicOp("+=", v.ident, IntegerExp.literal!(1));
4382 if (e is null)
4384 .error(scd.loc, "%s `%s` shared static constructor within a template require `core.atomic : atomicOp` to be present", scd.kind, scd.toPrettyChars);
4385 return;
4388 else
4390 e = new AddAssignExp(
4391 Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!1);
4394 e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!1);
4395 s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
4397 sa.push(s);
4398 if (scd.fbody)
4399 sa.push(scd.fbody);
4401 scd.fbody = new CompoundStatement(Loc.initial, sa);
4404 const LINK save = sc.linkage;
4405 if (save != LINK.d)
4407 const(char)* s = (scd.isSharedStaticCtorDeclaration() ? "shared " : "");
4408 deprecation(scd.loc, "`%sstatic` constructor can only be of D linkage", s);
4409 // Just correct it
4410 sc.linkage = LINK.d;
4412 funcDeclarationSemantic(scd);
4413 sc.linkage = save;
4415 // We're going to need ModuleInfo
4416 Module m = scd.getModule();
4417 if (!m)
4418 m = sc._module;
4419 if (m)
4421 m.needmoduleinfo = 1;
4422 //printf("module1 %s needs moduleinfo\n", m.toChars());
4426 override void visit(StaticDtorDeclaration sdd)
4428 if (sdd.semanticRun >= PASS.semanticdone)
4429 return;
4430 if (sdd._scope)
4432 sc = sdd._scope;
4433 sdd._scope = null;
4436 sdd.parent = sc.parent;
4437 Dsymbol p = sdd.parent.pastMixin();
4438 if (!p.isScopeDsymbol())
4440 const(char)* s = (sdd.isSharedStaticDtorDeclaration() ? "shared " : "");
4441 error(sdd.loc, "`%sstatic` destructor can only be member of module/aggregate/template, not %s `%s`", s, p.kind(), p.toChars());
4442 sdd.type = Type.terror;
4443 sdd.errors = true;
4444 return;
4446 if (!sdd.type)
4447 sdd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, sdd.storage_class);
4449 /* If the static ctor appears within a template instantiation,
4450 * it could get called multiple times by the module constructors
4451 * for different modules. Thus, protect it with a gate.
4453 if (sdd.isInstantiated() && sdd.semanticRun < PASS.semantic)
4455 /* Add this prefix to the constructor:
4456 * ```
4457 * static int gate;
4458 * if (--gate != 0) return;
4459 * ```
4460 * or, for shared constructor:
4461 * ```
4462 * shared int gate;
4463 * if (core.atomic.atomicOp!"-="(gate, 1) != 0) return;
4464 * ```
4466 const bool isShared = !!sdd.isSharedStaticDtorDeclaration();
4467 auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
4468 v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
4470 auto sa = new Statements();
4471 Statement s = new ExpStatement(Loc.initial, v);
4472 sa.push(s);
4474 Expression e;
4475 if (isShared)
4477 e = doAtomicOp("-=", v.ident, IntegerExp.literal!(1));
4478 if (e is null)
4480 .error(sdd.loc, "%s `%s` shared static destructo within a template require `core.atomic : atomicOp` to be present", sdd.kind, sdd.toPrettyChars);
4481 return;
4484 else
4486 e = new AddAssignExp(
4487 Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!(-1));
4490 e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!0);
4491 s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
4493 sa.push(s);
4494 if (sdd.fbody)
4495 sa.push(sdd.fbody);
4497 sdd.fbody = new CompoundStatement(Loc.initial, sa);
4499 sdd.vgate = v;
4502 const LINK save = sc.linkage;
4503 if (save != LINK.d)
4505 const(char)* s = (sdd.isSharedStaticDtorDeclaration() ? "shared " : "");
4506 deprecation(sdd.loc, "`%sstatic` destructor can only be of D linkage", s);
4507 // Just correct it
4508 sc.linkage = LINK.d;
4510 funcDeclarationSemantic(sdd);
4511 sc.linkage = save;
4513 // We're going to need ModuleInfo
4514 Module m = sdd.getModule();
4515 if (!m)
4516 m = sc._module;
4517 if (m)
4519 m.needmoduleinfo = 1;
4520 //printf("module2 %s needs moduleinfo\n", m.toChars());
4524 override void visit(InvariantDeclaration invd)
4526 if (invd.semanticRun >= PASS.semanticdone)
4527 return;
4528 if (invd._scope)
4530 sc = invd._scope;
4531 invd._scope = null;
4534 invd.parent = sc.parent;
4535 Dsymbol p = invd.parent.pastMixin();
4536 AggregateDeclaration ad = p.isAggregateDeclaration();
4537 if (!ad)
4539 error(invd.loc, "`invariant` can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
4540 invd.type = Type.terror;
4541 invd.errors = true;
4542 return;
4544 if (invd.ident != Id.classInvariant &&
4545 invd.semanticRun < PASS.semantic &&
4546 !ad.isUnionDeclaration() // users are on their own with union fields
4549 invd.fixupInvariantIdent(ad.invs.length);
4550 ad.invs.push(invd);
4552 if (!invd.type)
4553 invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class);
4555 sc = sc.push();
4556 sc.stc &= ~STC.static_; // not a static invariant
4557 sc.stc |= STC.const_; // invariant() is always const
4558 sc.flags = (sc.flags & ~SCOPE.contract) | SCOPE.invariant_;
4559 sc.linkage = LINK.d;
4561 funcDeclarationSemantic(invd);
4563 sc.pop();
4566 override void visit(UnitTestDeclaration utd)
4568 if (utd.semanticRun >= PASS.semanticdone)
4569 return;
4570 if (utd._scope)
4572 sc = utd._scope;
4573 utd._scope = null;
4576 utd.visibility = sc.visibility;
4578 utd.parent = sc.parent;
4579 Dsymbol p = utd.parent.pastMixin();
4580 if (!p.isScopeDsymbol())
4582 error(utd.loc, "`unittest` can only be a member of module/aggregate/template, not %s `%s`", p.kind(), p.toChars());
4583 utd.type = Type.terror;
4584 utd.errors = true;
4585 return;
4588 if (global.params.useUnitTests)
4590 if (!utd.type)
4591 utd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, utd.storage_class);
4592 Scope* sc2 = sc.push();
4593 sc2.linkage = LINK.d;
4594 funcDeclarationSemantic(utd);
4595 sc2.pop();
4598 version (none)
4600 // We're going to need ModuleInfo even if the unit tests are not
4601 // compiled in, because other modules may import this module and refer
4602 // to this ModuleInfo.
4603 // (This doesn't make sense to me?)
4604 Module m = utd.getModule();
4605 if (!m)
4606 m = sc._module;
4607 if (m)
4609 //printf("module3 %s needs moduleinfo\n", m.toChars());
4610 m.needmoduleinfo = 1;
4615 override void visit(NewDeclaration nd)
4617 //printf("NewDeclaration::semantic()\n");
4618 if (nd.semanticRun >= PASS.semanticdone)
4619 return;
4620 if (!nd.type)
4621 nd.type = new TypeFunction(ParameterList(), Type.tvoid.pointerTo(), LINK.d, nd.storage_class);
4623 funcDeclarationSemantic(nd);
4626 override void visit(StructDeclaration sd)
4628 enum log = false;
4629 if (log) printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4631 //static int count; if (++count == 20) assert(0);
4633 if (sd.semanticRun >= PASS.semanticdone)
4634 return;
4635 int errors = global.errors;
4637 //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4638 Scope* scx = null;
4639 if (sd._scope)
4641 sc = sd._scope;
4642 scx = sd._scope; // save so we don't make redundant copies
4643 sd._scope = null;
4646 if (!sd.parent)
4648 assert(sc.parent && sc.func);
4649 sd.parent = sc.parent;
4651 assert(sd.parent && !sd.isAnonymous());
4653 if (sd.errors)
4654 sd.type = Type.terror;
4655 if (sd.semanticRun == PASS.initial)
4656 sd.type = sd.type.addSTC(sc.stc | sd.storage_class);
4657 sd.type = sd.type.typeSemantic(sd.loc, sc);
4658 auto ts = sd.type.isTypeStruct();
4659 if (ts)
4661 if (ts.sym != sd)
4663 auto ti = ts.sym.isInstantiated();
4664 if (ti && isError(ti))
4665 ts.sym = sd;
4669 // Ungag errors when not speculative
4670 Ungag ungag = sd.ungagSpeculative();
4672 if (sd.semanticRun == PASS.initial)
4674 sd.visibility = sc.visibility;
4676 if (sd.alignment.isUnknown()) // can be set already by `struct __declspec(align(N)) Tag { ... }`
4677 sd.alignment = sc.alignment();
4679 sd.storage_class |= sc.stc;
4680 if (sd.storage_class & STC.abstract_)
4681 .error(sd.loc, "%s `%s` structs, unions cannot be `abstract`", sd.kind, sd.toPrettyChars);
4683 sd.userAttribDecl = sc.userAttribDecl;
4685 if (sc.linkage == LINK.cpp)
4686 sd.classKind = ClassKind.cpp;
4687 else if (sc.linkage == LINK.c)
4688 sd.classKind = ClassKind.c;
4689 sd.cppnamespace = sc.namespace;
4690 sd.cppmangle = sc.cppmangle;
4692 else if (sd.symtab && !scx)
4693 return;
4695 sd.semanticRun = PASS.semantic;
4696 UserAttributeDeclaration.checkGNUABITag(sd, sc.linkage);
4698 if (!sd.members) // if opaque declaration
4700 if (log) printf("\topaque declaration %s\n", sd.toChars());
4701 sd.semanticRun = PASS.semanticdone;
4702 return;
4704 if (!sd.symtab)
4706 sd.symtab = new DsymbolTable();
4708 sd.members.foreachDsymbol( s => s.addMember(sc, sd) );
4711 auto sc2 = sd.newScope(sc);
4713 /* Set scope so if there are forward references, we still might be able to
4714 * resolve individual members like enums.
4716 sd.members.foreachDsymbol( s => s.setScope(sc2) );
4717 sd.members.foreachDsymbol( s => s.importAll(sc2) );
4718 sd.members.foreachDsymbol( (s) { s.dsymbolSemantic(sc2); sd.errors |= s.errors; } );
4720 if (sd.errors)
4721 sd.type = Type.terror;
4723 if (!sd.determineFields())
4725 if (sd.type.ty != Terror)
4727 .error(sd.loc, "%s `%s` circular or forward reference", sd.kind, sd.toPrettyChars);
4728 sd.errors = true;
4729 sd.type = Type.terror;
4732 sc2.pop();
4733 sd.semanticRun = PASS.semanticdone;
4734 return;
4736 /* Following special member functions creation needs semantic analysis
4737 * completion of sub-structs in each field types. For example, buildDtor
4738 * needs to check existence of elaborate dtor in type of each fields.
4739 * See the case in compilable/test14838.d
4741 foreach (v; sd.fields)
4743 Type tb = v.type.baseElemOf();
4744 if (tb.ty != Tstruct)
4745 continue;
4746 auto sdec = (cast(TypeStruct)tb).sym;
4747 if (sdec.semanticRun >= PASS.semanticdone)
4748 continue;
4750 sc2.pop();
4752 if (log) printf("\tdeferring %s\n", sd.toChars());
4753 return deferDsymbolSemantic(sd, scx);
4756 /* Look for special member functions.
4758 sd.disableNew = sd.search(Loc.initial, Id.classNew) !is null;
4760 // Look for the constructor
4761 sd.ctor = sd.searchCtor();
4763 buildDtors(sd, sc2);
4765 sd.hasCopyCtor = buildCopyCtor(sd, sc2);
4766 sd.postblit = buildPostBlit(sd, sc2);
4768 buildOpAssign(sd, sc2);
4769 buildOpEquals(sd, sc2);
4771 if (!(sc2.flags & SCOPE.Cfile) &&
4772 global.params.useTypeInfo && Type.dtypeinfo) // these functions are used for TypeInfo
4774 sd.xeq = buildXopEquals(sd, sc2);
4775 sd.xcmp = buildXopCmp(sd, sc2);
4776 sd.xhash = buildXtoHash(sd, sc2);
4779 sd.inv = buildInv(sd, sc2);
4781 sd.semanticRun = PASS.semanticdone;
4782 if (log) printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4784 sc2.pop();
4786 if (sd.ctor)
4788 Dsymbol scall = sd.search(Loc.initial, Id.call);
4789 if (scall)
4791 uint xerrors = global.startGagging();
4792 sc = sc.push();
4793 sc.tinst = null;
4794 sc.minst = null;
4795 auto fcall = resolveFuncCall(sd.loc, sc, scall, null, null, ArgumentList(), FuncResolveFlag.quiet);
4796 sc = sc.pop();
4797 global.endGagging(xerrors);
4799 if (fcall && fcall.isStatic())
4801 .error(fcall.loc, "%s `%s` `static opCall` is hidden by constructors and can never be called", sd.kind, sd.toPrettyChars);
4802 errorSupplemental(fcall.loc, "Please use a factory method instead, or replace all constructors with `static opCall`.");
4807 if (ts && ts.sym != sd)
4809 StructDeclaration sym = ts.sym;
4810 if (sd.isCsymbol() && sym.isCsymbol())
4812 /* This is two structs imported from different C files.
4813 * Just ignore sd, the second one. The first one will always
4814 * be found when going through the type.
4817 else
4819 version (none)
4821 printf("this = %p %s\n", sd, sd.toChars());
4822 printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars());
4824 // https://issues.dlang.org/show_bug.cgi?id=19024
4825 .error(sd.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", sd.kind, sd.toPrettyChars, sym.loc.toChars());
4829 if (global.errors != errors)
4831 // The type is no good.
4832 sd.type = Type.terror;
4833 sd.errors = true;
4834 if (sd.deferred)
4835 sd.deferred.errors = true;
4838 if (sd.deferred && !global.gag)
4840 sd.deferred.semantic2(sc);
4841 sd.deferred.semantic3(sc);
4844 version (none)
4846 // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
4847 // Deprecated in 2.100
4848 // Make an error in 2.110
4849 if (sd.storage_class & STC.scope_)
4850 deprecation(sd.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
4852 //printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4855 void interfaceSemantic(ClassDeclaration cd)
4857 cd.vtblInterfaces = new BaseClasses();
4858 cd.vtblInterfaces.reserve(cd.interfaces.length);
4859 foreach (b; cd.interfaces)
4861 cd.vtblInterfaces.push(b);
4862 b.copyBaseInterfaces(cd.vtblInterfaces);
4866 override void visit(ClassDeclaration cldec)
4868 //printf("ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", cldec.toChars(), cldec.type, cldec.sizeok, this);
4869 //printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : "");
4870 //printf("sc.stc = %x\n", sc.stc);
4872 //{ static int n; if (++n == 20) *(char*)0=0; }
4874 if (cldec.semanticRun >= PASS.semanticdone)
4875 return;
4876 int errors = global.errors;
4878 //printf("+ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
4880 Scope* scx = null;
4881 if (cldec._scope)
4883 sc = cldec._scope;
4884 scx = cldec._scope; // save so we don't make redundant copies
4885 cldec._scope = null;
4888 if (!cldec.parent)
4890 assert(sc.parent);
4891 cldec.parent = sc.parent;
4894 if (cldec.errors)
4895 cldec.type = Type.terror;
4896 if (cldec.semanticRun == PASS.initial)
4897 cldec.type = cldec.type.addSTC(sc.stc | cldec.storage_class);
4898 cldec.type = cldec.type.typeSemantic(cldec.loc, sc);
4899 if (auto tc = cldec.type.isTypeClass())
4900 if (tc.sym != cldec)
4902 auto ti = tc.sym.isInstantiated();
4903 if (ti && isError(ti))
4904 tc.sym = cldec;
4907 // Ungag errors when not speculative
4908 Ungag ungag = cldec.ungagSpeculative();
4910 if (cldec.semanticRun == PASS.initial)
4912 cldec.visibility = sc.visibility;
4914 cldec.storage_class |= sc.stc;
4915 if (cldec.storage_class & STC.auto_)
4916 .error(cldec.loc, "%s `%s` storage class `auto` is invalid when declaring a class, did you mean to use `scope`?", cldec.kind, cldec.toPrettyChars);
4917 if (cldec.storage_class & STC.scope_)
4918 cldec.stack = true;
4919 if (cldec.storage_class & STC.abstract_)
4920 cldec.isabstract = ThreeState.yes;
4922 cldec.userAttribDecl = sc.userAttribDecl;
4924 if (sc.linkage == LINK.cpp)
4925 cldec.classKind = ClassKind.cpp;
4926 cldec.cppnamespace = sc.namespace;
4927 cldec.cppmangle = sc.cppmangle;
4928 if (sc.linkage == LINK.objc)
4929 objc.setObjc(cldec);
4931 else if (cldec.symtab && !scx)
4933 return;
4935 cldec.semanticRun = PASS.semantic;
4936 UserAttributeDeclaration.checkGNUABITag(cldec, sc.linkage);
4937 checkMustUseReserved(cldec);
4939 if (cldec.baseok < Baseok.done)
4941 /* https://issues.dlang.org/show_bug.cgi?id=12078
4942 * https://issues.dlang.org/show_bug.cgi?id=12143
4943 * https://issues.dlang.org/show_bug.cgi?id=15733
4944 * While resolving base classes and interfaces, a base may refer
4945 * the member of this derived class. In that time, if all bases of
4946 * this class can be determined, we can go forward the semantc process
4947 * beyond the Lancestorsdone. To do the recursive semantic analysis,
4948 * temporarily set and unset `_scope` around exp().
4950 T resolveBase(T)(lazy T exp)
4952 if (!scx)
4954 scx = sc.copy();
4955 scx.setNoFree();
4957 static if (!is(T == void))
4959 cldec._scope = scx;
4960 auto r = exp();
4961 cldec._scope = null;
4962 return r;
4964 else
4966 cldec._scope = scx;
4967 exp();
4968 cldec._scope = null;
4972 cldec.baseok = Baseok.start;
4974 // Expand any tuples in baseclasses[]
4975 for (size_t i = 0; i < cldec.baseclasses.length;)
4977 auto b = (*cldec.baseclasses)[i];
4978 b.type = resolveBase(b.type.typeSemantic(cldec.loc, sc));
4980 Type tb = b.type.toBasetype();
4981 if (auto tup = tb.isTypeTuple())
4983 cldec.baseclasses.remove(i);
4984 size_t dim = Parameter.dim(tup.arguments);
4985 for (size_t j = 0; j < dim; j++)
4987 Parameter arg = Parameter.getNth(tup.arguments, j);
4988 b = new BaseClass(arg.type);
4989 cldec.baseclasses.insert(i + j, b);
4992 else
4993 i++;
4996 if (cldec.baseok >= Baseok.done)
4998 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
4999 if (cldec.semanticRun >= PASS.semanticdone)
5000 return;
5001 goto Lancestorsdone;
5004 // See if there's a base class as first in baseclasses[]
5005 if (cldec.baseclasses.length)
5007 BaseClass* b = (*cldec.baseclasses)[0];
5008 Type tb = b.type.toBasetype();
5009 TypeClass tc = tb.isTypeClass();
5010 if (!tc)
5012 if (b.type != Type.terror)
5013 .error(cldec.loc, "%s `%s` base type must be `class` or `interface`, not `%s`", cldec.kind, cldec.toPrettyChars, b.type.toChars());
5014 cldec.baseclasses.remove(0);
5015 goto L7;
5017 if (tc.sym.isDeprecated())
5019 if (!cldec.isDeprecated())
5021 // Deriving from deprecated class makes this one deprecated too
5022 cldec.setDeprecated();
5023 tc.checkDeprecated(cldec.loc, sc);
5026 if (tc.sym.isInterfaceDeclaration())
5027 goto L7;
5029 for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass)
5031 if (cdb == cldec)
5033 .error(cldec.loc, "%s `%s` circular inheritance", cldec.kind, cldec.toPrettyChars);
5034 cldec.baseclasses.remove(0);
5035 goto L7;
5039 /* https://issues.dlang.org/show_bug.cgi?id=11034
5040 * Class inheritance hierarchy
5041 * and instance size of each classes are orthogonal information.
5042 * Therefore, even if tc.sym.sizeof == Sizeok.none,
5043 * we need to set baseClass field for class covariance check.
5045 cldec.baseClass = tc.sym;
5046 b.sym = cldec.baseClass;
5048 if (tc.sym.baseok < Baseok.done)
5049 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
5050 if (tc.sym.baseok < Baseok.done)
5052 //printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars());
5053 if (tc.sym._scope)
5054 Module.addDeferredSemantic(tc.sym);
5055 cldec.baseok = Baseok.none;
5060 // Treat the remaining entries in baseclasses as interfaces
5061 // Check for errors, handle forward references
5062 int multiClassError = cldec.baseClass is null ? 0 : 1;
5064 BCLoop:
5065 for (size_t i = (cldec.baseClass ? 1 : 0); i < cldec.baseclasses.length;)
5067 BaseClass* b = (*cldec.baseclasses)[i];
5068 Type tb = b.type.toBasetype();
5069 TypeClass tc = tb.isTypeClass();
5070 if (!tc || !tc.sym.isInterfaceDeclaration())
5072 // It's a class
5073 if (tc)
5075 if (multiClassError == 0)
5077 .error(cldec.loc,"`%s`: base class must be specified first, " ~
5078 "before any interfaces.", cldec.toPrettyChars());
5079 multiClassError += 1;
5081 else if (multiClassError >= 1)
5083 if(multiClassError == 1)
5084 .error(cldec.loc, "`%s`: multiple class inheritance is not supported." ~
5085 " Use multiple interface inheritance and/or composition.", cldec.toPrettyChars());
5086 multiClassError += 1;
5088 if (tc.sym.fields.length)
5089 errorSupplemental(cldec.loc,"`%s` has fields, consider making it a member of `%s`",
5090 b.type.toChars(), cldec.type.toChars());
5091 else
5092 errorSupplemental(cldec.loc,"`%s` has no fields, consider making it an `interface`",
5093 b.type.toChars());
5096 // It's something else: e.g. `int` in `class Foo : Bar, int { ... }`
5097 else if (b.type != Type.terror)
5099 error(cldec.loc,"`%s`: base type must be `interface`, not `%s`",
5100 cldec.toPrettyChars(), b.type.toChars());
5102 cldec.baseclasses.remove(i);
5103 continue;
5106 // Check for duplicate interfaces
5107 for (size_t j = (cldec.baseClass ? 1 : 0); j < i; j++)
5109 BaseClass* b2 = (*cldec.baseclasses)[j];
5110 if (b2.sym == tc.sym)
5112 .error(cldec.loc, "%s `%s` inherits from duplicate interface `%s`", cldec.kind, cldec.toPrettyChars, b2.sym.toChars());
5113 cldec.baseclasses.remove(i);
5114 continue BCLoop;
5117 if (tc.sym.isDeprecated())
5119 if (!cldec.isDeprecated())
5121 // Deriving from deprecated class makes this one deprecated too
5122 cldec.setDeprecated();
5123 tc.checkDeprecated(cldec.loc, sc);
5127 b.sym = tc.sym;
5129 if (tc.sym.baseok < Baseok.done)
5130 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
5131 if (tc.sym.baseok < Baseok.done)
5133 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
5134 if (tc.sym._scope)
5135 Module.addDeferredSemantic(tc.sym);
5136 cldec.baseok = Baseok.none;
5138 i++;
5140 if (cldec.baseok == Baseok.none)
5142 // Forward referencee of one or more bases, try again later
5143 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
5144 return deferDsymbolSemantic(cldec, scx);
5146 cldec.baseok = Baseok.done;
5148 if (cldec.classKind == ClassKind.objc || (cldec.baseClass && cldec.baseClass.classKind == ClassKind.objc))
5149 cldec.classKind = ClassKind.objc; // Objective-C classes do not inherit from Object
5151 // If no base class, and this is not an Object, use Object as base class
5152 if (!cldec.baseClass && cldec.ident != Id.Object && cldec.object && cldec.classKind == ClassKind.d)
5154 void badObjectDotD()
5156 .error(cldec.loc, "%s `%s` missing or corrupt object.d", cldec.kind, cldec.toPrettyChars);
5157 fatal();
5160 if (!cldec.object || cldec.object.errors)
5161 badObjectDotD();
5163 Type t = cldec.object.type;
5164 t = t.typeSemantic(cldec.loc, sc).toBasetype();
5165 if (t.ty == Terror)
5166 badObjectDotD();
5167 TypeClass tc = t.isTypeClass();
5168 assert(tc);
5170 auto b = new BaseClass(tc);
5171 cldec.baseclasses.shift(b);
5173 cldec.baseClass = tc.sym;
5174 assert(!cldec.baseClass.isInterfaceDeclaration());
5175 b.sym = cldec.baseClass;
5177 if (cldec.baseClass)
5179 if (cldec.baseClass.storage_class & STC.final_)
5180 .error(cldec.loc, "%s `%s` cannot inherit from class `%s` because it is `final`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
5182 // Inherit properties from base class
5183 if (cldec.baseClass.isCOMclass())
5184 cldec.com = true;
5185 if (cldec.baseClass.isCPPclass())
5186 cldec.classKind = ClassKind.cpp;
5187 if (cldec.classKind != cldec.baseClass.classKind)
5188 .error(cldec.loc, "%s `%s` with %s linkage cannot inherit from class `%s` with %s linkage", cldec.kind, cldec.toPrettyChars,
5189 cldec.classKind.toChars(), cldec.baseClass.toChars(), cldec.baseClass.classKind.toChars());
5191 if (cldec.baseClass.stack)
5192 cldec.stack = true;
5193 cldec.enclosing = cldec.baseClass.enclosing;
5194 cldec.storage_class |= cldec.baseClass.storage_class & STC.TYPECTOR;
5197 cldec.interfaces = cldec.baseclasses.tdata()[(cldec.baseClass ? 1 : 0) .. cldec.baseclasses.length];
5198 foreach (b; cldec.interfaces)
5200 // If this is an interface, and it derives from a COM interface,
5201 // then this is a COM interface too.
5202 if (b.sym.isCOMinterface())
5203 cldec.com = true;
5204 if (cldec.classKind == ClassKind.cpp && !b.sym.isCPPinterface())
5206 .error(cldec.loc, "C++ class `%s` cannot implement D interface `%s`",
5207 cldec.toPrettyChars(), b.sym.toPrettyChars());
5210 interfaceSemantic(cldec);
5212 Lancestorsdone:
5213 //printf("\tClassDeclaration.dsymbolSemantic(%s) baseok = %d\n", toChars(), baseok);
5215 if (!cldec.members) // if opaque declaration
5217 cldec.semanticRun = PASS.semanticdone;
5218 return;
5220 if (!cldec.symtab)
5222 cldec.symtab = new DsymbolTable();
5224 /* https://issues.dlang.org/show_bug.cgi?id=12152
5225 * The semantic analysis of base classes should be finished
5226 * before the members semantic analysis of this class, in order to determine
5227 * vtbl in this class. However if a base class refers the member of this class,
5228 * it can be resolved as a normal forward reference.
5229 * Call addMember() and setScope() to make this class members visible from the base classes.
5231 cldec.members.foreachDsymbol( s => s.addMember(sc, cldec) );
5233 auto sc2 = cldec.newScope(sc);
5235 /* Set scope so if there are forward references, we still might be able to
5236 * resolve individual members like enums.
5238 cldec.members.foreachDsymbol( s => s.setScope(sc2) );
5240 sc2.pop();
5243 for (size_t i = 0; i < cldec.baseclasses.length; i++)
5245 BaseClass* b = (*cldec.baseclasses)[i];
5246 Type tb = b.type.toBasetype();
5247 TypeClass tc = tb.isTypeClass();
5248 if (tc.sym.semanticRun < PASS.semanticdone)
5250 // Forward referencee of one or more bases, try again later
5251 if (tc.sym._scope)
5252 Module.addDeferredSemantic(tc.sym);
5253 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
5254 return deferDsymbolSemantic(cldec, scx);
5258 if (cldec.baseok == Baseok.done)
5260 cldec.baseok = Baseok.semanticdone;
5261 objc.setMetaclass(cldec, sc);
5263 // initialize vtbl
5264 if (cldec.baseClass)
5266 if (cldec.classKind == ClassKind.cpp && cldec.baseClass.vtbl.length == 0)
5268 .error(cldec.loc, "%s `%s` C++ base class `%s` needs at least one virtual function", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
5271 // Copy vtbl[] from base class
5272 assert(cldec.vtbl.length == 0);
5273 cldec.vtbl.setDim(cldec.baseClass.vtbl.length);
5274 memcpy(cldec.vtbl.tdata(), cldec.baseClass.vtbl.tdata(), (void*).sizeof * cldec.vtbl.length);
5276 cldec.vthis = cldec.baseClass.vthis;
5277 cldec.vthis2 = cldec.baseClass.vthis2;
5279 else
5281 // No base class, so this is the root of the class hierarchy
5282 cldec.vtbl.setDim(0);
5283 if (cldec.vtblOffset())
5284 cldec.vtbl.push(cldec); // leave room for classinfo as first member
5287 /* If this is a nested class, add the hidden 'this'
5288 * member which is a pointer to the enclosing scope.
5290 if (cldec.vthis) // if inheriting from nested class
5292 // Use the base class's 'this' member
5293 if (cldec.storage_class & STC.static_)
5294 .error(cldec.loc, "%s `%s` static class cannot inherit from nested class `%s`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
5295 if (cldec.toParentLocal() != cldec.baseClass.toParentLocal() &&
5296 (!cldec.toParentLocal() ||
5297 !cldec.baseClass.toParentLocal().getType() ||
5298 !cldec.baseClass.toParentLocal().getType().isBaseOf(cldec.toParentLocal().getType(), null)))
5300 if (cldec.toParentLocal())
5302 .error(cldec.loc, "%s `%s` is nested within `%s`, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
5303 cldec.toParentLocal().toChars(),
5304 cldec.baseClass.toChars(),
5305 cldec.baseClass.toParentLocal().toChars());
5307 else
5309 .error(cldec.loc, "%s `%s` is not nested, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
5310 cldec.baseClass.toChars(),
5311 cldec.baseClass.toParentLocal().toChars());
5314 if (cldec.vthis2)
5316 if (cldec.toParent2() != cldec.baseClass.toParent2() &&
5317 (!cldec.toParent2() ||
5318 !cldec.baseClass.toParent2().getType() ||
5319 !cldec.baseClass.toParent2().getType().isBaseOf(cldec.toParent2().getType(), null)))
5321 if (cldec.toParent2() && cldec.toParent2() != cldec.toParentLocal())
5323 .error(cldec.loc, "%s `%s` needs the frame pointer of `%s`, but super class `%s` needs the frame pointer of `%s`", cldec.kind, cldec.toPrettyChars,
5324 cldec.toParent2().toChars(),
5325 cldec.baseClass.toChars(),
5326 cldec.baseClass.toParent2().toChars());
5328 else
5330 .error(cldec.loc, "%s `%s` doesn't need a frame pointer, but super class `%s` needs the frame pointer of `%s`", cldec.kind, cldec.toPrettyChars,
5331 cldec.baseClass.toChars(),
5332 cldec.baseClass.toParent2().toChars());
5336 else
5337 cldec.makeNested2();
5339 else
5340 cldec.makeNested();
5343 auto sc2 = cldec.newScope(sc);
5345 cldec.members.foreachDsymbol( s => s.importAll(sc2) );
5347 // Note that members.length can grow due to tuple expansion during semantic()
5348 cldec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
5350 if (!cldec.determineFields())
5352 assert(cldec.type == Type.terror);
5353 sc2.pop();
5354 return;
5356 /* Following special member functions creation needs semantic analysis
5357 * completion of sub-structs in each field types.
5359 foreach (v; cldec.fields)
5361 Type tb = v.type.baseElemOf();
5362 if (tb.ty != Tstruct)
5363 continue;
5364 auto sd = (cast(TypeStruct)tb).sym;
5365 if (sd.semanticRun >= PASS.semanticdone)
5366 continue;
5368 sc2.pop();
5370 //printf("\tdeferring %s\n", toChars());
5371 return deferDsymbolSemantic(cldec, scx);
5374 /* Look for special member functions.
5375 * They must be in this class, not in a base class.
5377 // Can be in base class
5378 cldec.disableNew = cldec.search(Loc.initial, Id.classNew) !is null;
5380 // Look for the constructor
5381 cldec.ctor = cldec.searchCtor();
5383 if (!cldec.ctor && cldec.noDefaultCtor)
5385 // A class object is always created by constructor, so this check is legitimate.
5386 foreach (v; cldec.fields)
5388 if (v.storage_class & STC.nodefaultctor)
5389 error(v.loc, "field `%s` must be initialized in constructor", v.toChars());
5393 // If this class has no constructor, but base class has a default
5394 // ctor, create a constructor:
5395 // this() { }
5396 if (!cldec.ctor && cldec.baseClass && cldec.baseClass.ctor)
5398 auto fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type, ArgumentList(), FuncResolveFlag.quiet);
5399 if (!fd) // try shared base ctor instead
5400 fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type.sharedOf, ArgumentList(), FuncResolveFlag.quiet);
5401 if (fd && !fd.errors)
5403 //printf("Creating default this(){} for class %s\n", toChars());
5404 auto btf = fd.type.toTypeFunction();
5405 auto tf = new TypeFunction(ParameterList(), null, LINK.d, fd.storage_class);
5406 tf.mod = btf.mod;
5407 // Don't copy @safe, ... from the base class constructor and let it be inferred instead
5408 // This is required if other lowerings add code to the generated constructor which
5409 // is less strict (e.g. `preview=dtorfields` might introduce a call to a less qualified dtor)
5411 auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf);
5412 ctor.storage_class |= STC.inference | (fd.storage_class & STC.scope_);
5413 ctor.isGenerated = true;
5414 ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
5416 cldec.members.push(ctor);
5417 ctor.addMember(sc, cldec);
5418 ctor.dsymbolSemantic(sc2);
5420 cldec.ctor = ctor;
5421 cldec.defaultCtor = ctor;
5423 else
5425 .error(cldec.loc, "%s `%s` cannot implicitly generate a default constructor when base class `%s` is missing a default constructor", cldec.kind, cldec.toPrettyChars,
5426 cldec.baseClass.toPrettyChars());
5430 buildDtors(cldec, sc2);
5432 if (cldec.classKind == ClassKind.cpp && cldec.cppDtorVtblIndex != -1)
5434 // now we've built the aggregate destructor, we'll make it virtual and assign it to the reserved vtable slot
5435 cldec.dtor.vtblIndex = cldec.cppDtorVtblIndex;
5436 cldec.vtbl[cldec.cppDtorVtblIndex] = cldec.dtor;
5438 if (target.cpp.twoDtorInVtable)
5440 // TODO: create a C++ compatible deleting destructor (call out to `operator delete`)
5441 // for the moment, we'll call the non-deleting destructor and leak
5442 cldec.vtbl[cldec.cppDtorVtblIndex + 1] = cldec.dtor;
5446 if (auto f = hasIdentityOpAssign(cldec, sc2))
5448 if (!(f.storage_class & STC.disable))
5449 .error(f.loc, "%s `%s` identity assignment operator overload is illegal", cldec.kind, cldec.toPrettyChars);
5452 cldec.inv = buildInv(cldec, sc2);
5454 cldec.semanticRun = PASS.semanticdone;
5455 //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5457 sc2.pop();
5459 /* isAbstract() is undecidable in some cases because of circular dependencies.
5460 * Now that semantic is finished, get a definitive result, and error if it is not the same.
5462 if (cldec.isabstract != ThreeState.none) // if evaluated it before completion
5464 const isabstractsave = cldec.isabstract;
5465 cldec.isabstract = ThreeState.none;
5466 cldec.isAbstract(); // recalculate
5467 if (cldec.isabstract != isabstractsave)
5469 .error(cldec.loc, "%s `%s` cannot infer `abstract` attribute due to circular dependencies", cldec.kind, cldec.toPrettyChars);
5473 if (cldec.type.ty == Tclass && (cast(TypeClass)cldec.type).sym != cldec)
5475 // https://issues.dlang.org/show_bug.cgi?id=17492
5476 ClassDeclaration cd = (cast(TypeClass)cldec.type).sym;
5477 version (none)
5479 printf("this = %p %s\n", cldec, cldec.toPrettyChars());
5480 printf("type = %d sym = %p, %s\n", cldec.type.ty, cd, cd.toPrettyChars());
5482 .error(cldec.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", cldec.kind, cldec.toPrettyChars, cd.loc.toChars());
5485 if (global.errors != errors || (cldec.baseClass && cldec.baseClass.errors))
5487 // The type is no good, but we should keep the
5488 // the type so that we have more accurate error messages
5489 // See: https://issues.dlang.org/show_bug.cgi?id=23552
5490 cldec.errors = true;
5491 if (cldec.deferred)
5492 cldec.deferred.errors = true;
5495 // Verify fields of a synchronized class are not public
5496 if (cldec.storage_class & STC.synchronized_)
5498 foreach (vd; cldec.fields)
5500 if (!vd.isThisDeclaration() &&
5501 vd.visible() >= Visibility(Visibility.Kind.public_))
5503 .error(vd.loc, "%s `%s` Field members of a `synchronized` class cannot be `%s`", vd.kind, vd.toPrettyChars,
5504 visibilityToChars(vd.visible().kind));
5509 if (cldec.deferred && !global.gag)
5511 cldec.deferred.semantic2(sc);
5512 cldec.deferred.semantic3(sc);
5514 //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
5516 version (none)
5518 // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
5519 // Deprecated in 2.100
5520 // Make an error in 2.110
5521 // Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
5522 if (cldec.storage_class & STC.scope_)
5523 deprecation(cldec.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
5527 override void visit(InterfaceDeclaration idec)
5529 /// Returns: `true` is this is an anonymous Objective-C metaclass
5530 static bool isAnonymousMetaclass(InterfaceDeclaration idec)
5532 return idec.classKind == ClassKind.objc &&
5533 idec.objc.isMeta &&
5534 idec.isAnonymous;
5537 //printf("InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5538 if (idec.semanticRun >= PASS.semanticdone)
5539 return;
5540 int errors = global.errors;
5542 //printf("+InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5544 Scope* scx = null;
5545 if (idec._scope)
5547 sc = idec._scope;
5548 scx = idec._scope; // save so we don't make redundant copies
5549 idec._scope = null;
5552 if (!idec.parent)
5554 assert(sc.parent && sc.func);
5555 idec.parent = sc.parent;
5557 // Objective-C metaclasses are anonymous
5558 assert(idec.parent && !idec.isAnonymous || isAnonymousMetaclass(idec));
5560 if (idec.errors)
5561 idec.type = Type.terror;
5562 idec.type = idec.type.typeSemantic(idec.loc, sc);
5563 if (idec.type.ty == Tclass && (cast(TypeClass)idec.type).sym != idec)
5565 auto ti = (cast(TypeClass)idec.type).sym.isInstantiated();
5566 if (ti && isError(ti))
5567 (cast(TypeClass)idec.type).sym = idec;
5570 // Ungag errors when not speculative
5571 Ungag ungag = idec.ungagSpeculative();
5573 if (idec.semanticRun == PASS.initial)
5575 idec.visibility = sc.visibility;
5577 idec.storage_class |= sc.stc;
5578 idec.userAttribDecl = sc.userAttribDecl;
5580 else if (idec.symtab)
5582 if (idec.sizeok == Sizeok.done || !scx)
5584 idec.semanticRun = PASS.semanticdone;
5585 return;
5588 idec.semanticRun = PASS.semantic;
5590 if (idec.baseok < Baseok.done)
5592 T resolveBase(T)(lazy T exp)
5594 if (!scx)
5596 scx = sc.copy();
5597 scx.setNoFree();
5599 static if (!is(T == void))
5601 idec._scope = scx;
5602 auto r = exp();
5603 idec._scope = null;
5604 return r;
5606 else
5608 idec._scope = scx;
5609 exp();
5610 idec._scope = null;
5614 idec.baseok = Baseok.start;
5616 // Expand any tuples in baseclasses[]
5617 for (size_t i = 0; i < idec.baseclasses.length;)
5619 auto b = (*idec.baseclasses)[i];
5620 b.type = resolveBase(b.type.typeSemantic(idec.loc, sc));
5622 Type tb = b.type.toBasetype();
5623 if (auto tup = tb.isTypeTuple())
5625 idec.baseclasses.remove(i);
5626 size_t dim = Parameter.dim(tup.arguments);
5627 for (size_t j = 0; j < dim; j++)
5629 Parameter arg = Parameter.getNth(tup.arguments, j);
5630 b = new BaseClass(arg.type);
5631 idec.baseclasses.insert(i + j, b);
5634 else
5635 i++;
5638 if (idec.baseok >= Baseok.done)
5640 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
5641 if (idec.semanticRun >= PASS.semanticdone)
5642 return;
5643 goto Lancestorsdone;
5646 if (!idec.baseclasses.length && sc.linkage == LINK.cpp)
5647 idec.classKind = ClassKind.cpp;
5648 idec.cppnamespace = sc.namespace;
5649 UserAttributeDeclaration.checkGNUABITag(idec, sc.linkage);
5650 checkMustUseReserved(idec);
5652 if (sc.linkage == LINK.objc)
5653 objc.setObjc(idec);
5655 // Check for errors, handle forward references
5656 BCLoop:
5657 for (size_t i = 0; i < idec.baseclasses.length;)
5659 BaseClass* b = (*idec.baseclasses)[i];
5660 Type tb = b.type.toBasetype();
5661 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null;
5662 if (!tc || !tc.sym.isInterfaceDeclaration())
5664 if (b.type != Type.terror)
5665 .error(idec.loc, "%s `%s` base type must be `interface`, not `%s`", idec.kind, idec.toPrettyChars, b.type.toChars());
5666 idec.baseclasses.remove(i);
5667 continue;
5670 // Check for duplicate interfaces
5671 for (size_t j = 0; j < i; j++)
5673 BaseClass* b2 = (*idec.baseclasses)[j];
5674 if (b2.sym == tc.sym)
5676 .error(idec.loc, "%s `%s` inherits from duplicate interface `%s`", idec.kind, idec.toPrettyChars, b2.sym.toChars());
5677 idec.baseclasses.remove(i);
5678 continue BCLoop;
5681 if (tc.sym == idec || idec.isBaseOf2(tc.sym))
5683 .error(idec.loc, "%s `%s` circular inheritance of interface", idec.kind, idec.toPrettyChars);
5684 idec.baseclasses.remove(i);
5685 continue;
5687 if (tc.sym.isDeprecated())
5689 if (!idec.isDeprecated())
5691 // Deriving from deprecated interface makes this one deprecated too
5692 idec.setDeprecated();
5693 tc.checkDeprecated(idec.loc, sc);
5697 b.sym = tc.sym;
5699 if (tc.sym.baseok < Baseok.done)
5700 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
5701 if (tc.sym.baseok < Baseok.done)
5703 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
5704 if (tc.sym._scope)
5705 Module.addDeferredSemantic(tc.sym);
5706 idec.baseok = Baseok.none;
5708 i++;
5710 if (idec.baseok == Baseok.none)
5712 // Forward referencee of one or more bases, try again later
5713 return deferDsymbolSemantic(idec, scx);
5715 idec.baseok = Baseok.done;
5717 idec.interfaces = idec.baseclasses.tdata()[0 .. idec.baseclasses.length];
5718 foreach (b; idec.interfaces)
5720 // If this is an interface, and it derives from a COM interface,
5721 // then this is a COM interface too.
5722 if (b.sym.isCOMinterface())
5723 idec.com = true;
5724 if (b.sym.isCPPinterface())
5725 idec.classKind = ClassKind.cpp;
5728 interfaceSemantic(idec);
5730 Lancestorsdone:
5732 if (!idec.members) // if opaque declaration
5734 idec.semanticRun = PASS.semanticdone;
5735 return;
5737 if (!idec.symtab)
5738 idec.symtab = new DsymbolTable();
5740 for (size_t i = 0; i < idec.baseclasses.length; i++)
5742 BaseClass* b = (*idec.baseclasses)[i];
5743 Type tb = b.type.toBasetype();
5744 TypeClass tc = tb.isTypeClass();
5745 if (tc.sym.semanticRun < PASS.semanticdone)
5747 // Forward referencee of one or more bases, try again later
5748 if (tc.sym._scope)
5749 Module.addDeferredSemantic(tc.sym);
5750 return deferDsymbolSemantic(idec, scx);
5754 if (idec.baseok == Baseok.done)
5756 idec.baseok = Baseok.semanticdone;
5757 objc.setMetaclass(idec, sc);
5759 // initialize vtbl
5760 if (idec.vtblOffset())
5761 idec.vtbl.push(idec); // leave room at vtbl[0] for classinfo
5763 // Cat together the vtbl[]'s from base interfaces
5764 foreach (i, b; idec.interfaces)
5766 // Skip if b has already appeared
5767 for (size_t k = 0; k < i; k++)
5769 if (b == idec.interfaces[k])
5770 goto Lcontinue;
5773 // Copy vtbl[] from base class
5774 if (b.sym.vtblOffset())
5776 size_t d = b.sym.vtbl.length;
5777 if (d > 1)
5779 idec.vtbl.pushSlice(b.sym.vtbl[1 .. d]);
5782 else
5784 idec.vtbl.append(&b.sym.vtbl);
5787 Lcontinue:
5791 idec.members.foreachDsymbol( s => s.addMember(sc, idec) );
5793 auto sc2 = idec.newScope(sc);
5795 /* Set scope so if there are forward references, we still might be able to
5796 * resolve individual members like enums.
5798 idec.members.foreachDsymbol( s => s.setScope(sc2) );
5800 idec.members.foreachDsymbol( s => s.importAll(sc2) );
5802 idec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
5804 idec.semanticRun = PASS.semanticdone;
5805 //printf("-InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5807 sc2.pop();
5809 if (global.errors != errors)
5811 // The type is no good.
5812 idec.type = Type.terror;
5815 version (none)
5817 if (type.ty == Tclass && (cast(TypeClass)idec.type).sym != idec)
5819 printf("this = %p %s\n", idec, idec.toChars());
5820 printf("type = %d sym = %p\n", idec.type.ty, (cast(TypeClass)idec.type).sym);
5823 assert(idec.type.ty != Tclass || (cast(TypeClass)idec.type).sym == idec);
5825 version (none)
5827 // @@@DEPRECATED_2.120@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
5828 // Deprecated in 2.087
5829 // Made an error in 2.100, but removal depends on `scope class` being removed too
5830 // Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
5831 if (idec.storage_class & STC.scope_)
5832 error(idec.loc, "`scope` as a type constraint is obsolete. Use `scope` at the usage site.");
5838 Adds dsym as a member of scope sds.
5840 Params:
5841 dsym = dsymbol to inserted
5842 sc = scope where the dsymbol is declared
5843 sds = ScopeDsymbol where dsym is inserted
5845 extern(C++) void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
5847 auto addMemberVisitor = new AddMemberVisitor(sc, sds);
5848 dsym.accept(addMemberVisitor);
5851 private void attribAddMember(AttribDeclaration atb, Scope* sc, ScopeDsymbol sds)
5853 Dsymbols* d = atb.include(sc);
5854 if (d)
5856 Scope* sc2 = atb.newScope(sc);
5857 d.foreachDsymbol( s => s.addMember(sc2, sds) );
5858 if (sc2 != sc)
5859 sc2.pop();
5863 private extern(C++) class AddMemberVisitor : Visitor
5865 alias visit = Visitor.visit;
5867 Scope* sc;
5868 ScopeDsymbol sds;
5870 this(Scope* sc, ScopeDsymbol sds)
5872 this.sc = sc;
5873 this.sds = sds;
5876 override void visit(Dsymbol dsym)
5878 //printf("Dsymbol::addMember('%s')\n", toChars());
5879 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars());
5880 //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab);
5881 dsym.parent = sds;
5882 if (dsym.isAnonymous()) // no name, so can't add it to symbol table
5883 return;
5885 if (!sds.symtabInsert(dsym)) // if name is already defined
5887 if (dsym.isAliasDeclaration() && !dsym._scope)
5888 dsym.setScope(sc);
5889 Dsymbol s2 = sds.symtabLookup(dsym, dsym.ident);
5890 /* https://issues.dlang.org/show_bug.cgi?id=17434
5892 * If we are trying to add an import to the symbol table
5893 * that has already been introduced, then keep the one with
5894 * larger visibility. This is fine for imports because if
5895 * we have multiple imports of the same file, if a single one
5896 * is public then the symbol is reachable.
5898 if (auto i1 = dsym.isImport())
5900 if (auto i2 = s2.isImport())
5902 if (sc.explicitVisibility && sc.visibility > i2.visibility)
5903 sds.symtab.update(dsym);
5907 // If using C tag/prototype/forward declaration rules
5908 if (sc.flags & SCOPE.Cfile && !dsym.isImport())
5910 if (handleTagSymbols(*sc, dsym, s2, sds))
5911 return;
5912 if (handleSymbolRedeclarations(*sc, dsym, s2, sds))
5913 return;
5915 sds.multiplyDefined(Loc.initial, dsym, s2); // ImportC doesn't allow overloading
5916 dsym.errors = true;
5917 return;
5920 if (!s2.overloadInsert(dsym))
5922 sds.multiplyDefined(Loc.initial, dsym, s2);
5923 dsym.errors = true;
5926 if (sds.isAggregateDeclaration() || sds.isEnumDeclaration())
5928 if (dsym.ident == Id.__sizeof ||
5929 !(sc && sc.flags & SCOPE.Cfile) && (dsym.ident == Id.__xalignof || dsym.ident == Id._mangleof))
5931 .error(dsym.loc, "%s `%s` `.%s` property cannot be redefined", dsym.kind, dsym.toPrettyChars, dsym.ident.toChars());
5932 dsym.errors = true;
5938 override void visit(StaticAssert _)
5940 // we didn't add anything
5943 /*****************************
5944 * Add import to sd's symbol table.
5946 override void visit(Import imp)
5948 //printf("Import.addMember(this=%s, sds=%s, sc=%p)\n", imp.toChars(), sds.toChars(), sc);
5949 if (imp.names.length == 0)
5950 return visit(cast(Dsymbol)imp);
5951 if (imp.aliasId)
5952 visit(cast(Dsymbol)imp);
5954 /* Instead of adding the import to sds's symbol table,
5955 * add each of the alias=name pairs
5957 for (size_t i = 0; i < imp.names.length; i++)
5959 Identifier name = imp.names[i];
5960 Identifier _alias = imp.aliases[i];
5961 if (!_alias)
5962 _alias = name;
5963 auto tname = new TypeIdentifier(imp.loc, name);
5964 auto ad = new AliasDeclaration(imp.loc, _alias, tname);
5965 ad._import = imp;
5966 addMember(ad, sc, sds);
5967 imp.aliasdecls.push(ad);
5971 override void visit(AttribDeclaration atb)
5973 attribAddMember(atb, sc, sds);
5976 override void visit(StorageClassDeclaration stcd)
5978 Dsymbols* d = stcd.include(sc);
5979 if (d)
5981 Scope* sc2 = stcd.newScope(sc);
5983 d.foreachDsymbol( (s)
5985 //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars());
5986 // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol)
5987 if (auto decl = s.isDeclaration())
5989 decl.storage_class |= stcd.stc & STC.local;
5990 if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case?
5992 sdecl.stc |= stcd.stc & STC.local;
5995 s.addMember(sc2, sds);
5998 if (sc2 != sc)
5999 sc2.pop();
6003 override void visit(VisibilityDeclaration visd)
6005 if (visd.pkg_identifiers)
6007 Dsymbol tmp;
6008 Package.resolve(visd.pkg_identifiers, &tmp, null);
6009 visd.visibility.pkg = tmp ? tmp.isPackage() : null;
6010 visd.pkg_identifiers = null;
6012 if (visd.visibility.kind == Visibility.Kind.package_ && visd.visibility.pkg && sc._module)
6014 Module m = sc._module;
6016 // https://issues.dlang.org/show_bug.cgi?id=17441
6017 // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if
6018 // each package's .isModule() properites are equal.
6020 // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
6021 // This breaks package declarations of the package in question if they are declared in
6022 // the same package.d file, which _do_ have a module associated with them, and hence a non-null
6023 // isModule()
6024 if (!m.isPackage() || !visd.visibility.pkg.ident.equals(m.isPackage().ident))
6026 Package pkg = m.parent ? m.parent.isPackage() : null;
6027 if (!pkg || !visd.visibility.pkg.isAncestorPackageOf(pkg))
6028 .error(visd.loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", visd.kind(), visd.toPrettyChars(false), m.toPrettyChars(true));
6031 attribAddMember(visd, sc, sds);
6034 override void visit(StaticIfDeclaration sid)
6036 //printf("StaticIfDeclaration::addMember() '%s'\n", sid.toChars());
6037 /* This is deferred until the condition evaluated later (by the include() call),
6038 * so that expressions in the condition can refer to declarations
6039 * in the same scope, such as:
6041 * template Foo(int i)
6043 * const int j = i + 1;
6044 * static if (j == 3)
6045 * const int k;
6048 sid.scopesym = sds;
6052 override void visit(StaticForeachDeclaration sfd)
6054 // used only for caching the enclosing symbol
6055 sfd.scopesym = sds;
6058 /***************************************
6059 * Lazily initializes the scope to forward to.
6061 override void visit(ForwardingAttribDeclaration fad)
6063 fad.sym.parent = sds;
6064 sds = fad.sym;
6065 attribAddMember(fad, sc, fad.sym);
6068 override void visit(MixinDeclaration md)
6070 //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, md.memnum);
6071 md.scopesym = sds;
6074 override void visit(DebugSymbol ds)
6076 //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), ds.toChars());
6077 Module m = sds.isModule();
6078 // Do not add the member to the symbol table,
6079 // just make sure subsequent debug declarations work.
6080 if (ds.ident)
6082 if (!m)
6084 .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
6085 ds.errors = true;
6087 else
6089 if (findCondition(m.debugidsNot, ds.ident))
6091 .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
6092 ds.errors = true;
6094 if (!m.debugids)
6095 m.debugids = new Identifiers();
6096 m.debugids.push(ds.ident);
6099 else
6101 if (!m)
6103 .error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
6104 ds.errors = true;
6106 else
6107 m.debuglevel = ds.level;
6111 override void visit(VersionSymbol vs)
6113 //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), vs.toChars());
6114 Module m = sds.isModule();
6115 // Do not add the member to the symbol table,
6116 // just make sure subsequent debug declarations work.
6117 if (vs.ident)
6119 VersionCondition.checkReserved(vs.loc, vs.ident.toString());
6120 if (!m)
6122 .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
6123 vs.errors = true;
6125 else
6127 if (findCondition(m.versionidsNot, vs.ident))
6129 .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
6130 vs.errors = true;
6132 if (!m.versionids)
6133 m.versionids = new Identifiers();
6134 m.versionids.push(vs.ident);
6137 else
6139 if (!m)
6141 .error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
6142 vs.errors = true;
6144 else
6145 m.versionlevel = vs.level;
6149 override void visit(Nspace ns)
6151 visit(cast(Dsymbol)ns);
6153 if (ns.members)
6155 if (!ns.symtab)
6156 ns.symtab = new DsymbolTable();
6157 // The namespace becomes 'imported' into the enclosing scope
6158 for (Scope* sce = sc; 1; sce = sce.enclosing)
6160 ScopeDsymbol sds2 = sce.scopesym;
6161 if (sds2)
6163 sds2.importScope(ns, Visibility(Visibility.Kind.public_));
6164 break;
6167 assert(sc);
6168 sc = sc.push(ns);
6169 sc.linkage = LINK.cpp; // namespaces default to C++ linkage
6170 sc.parent = ns;
6171 ns.members.foreachDsymbol(s => s.addMember(sc, ns));
6172 sc.pop();
6176 override void visit(EnumDeclaration ed)
6178 version (none)
6180 printf("EnumDeclaration::addMember() %s\n", ed.toChars());
6181 for (size_t i = 0; i < ed.members.length; i++)
6183 EnumMember em = (*ed.members)[i].isEnumMember();
6184 printf(" member %s\n", em.toChars());
6187 if (!ed.isAnonymous())
6189 visit(cast(Dsymbol)ed);
6192 addEnumMembersToSymtab(ed, sc, sds);
6196 /*******************************************
6197 * Add members of EnumDeclaration to the symbol table(s).
6198 * Params:
6199 * ed = EnumDeclaration
6200 * sc = context of `ed`
6201 * sds = symbol table that `ed` resides in
6203 void addEnumMembersToSymtab(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
6205 const bool isCEnum = (sc.flags & SCOPE.Cfile) != 0; // it's an ImportC enum
6206 //printf("addEnumMembersToSymtab(ed: %s added: %d Cfile: %d)\n", ed.toChars(), ed.added, isCEnum);
6207 if (ed.added)
6208 return;
6209 ed.added = true;
6211 if (!ed.members)
6212 return;
6214 const bool isAnon = ed.isAnonymous();
6216 if ((isCEnum || isAnon) && !sds.symtab)
6217 sds.symtab = new DsymbolTable();
6219 if ((isCEnum || !isAnon) && !ed.symtab)
6220 ed.symtab = new DsymbolTable();
6222 ed.members.foreachDsymbol( (s)
6224 if (EnumMember em = s.isEnumMember())
6226 //printf("adding EnumMember %s to %s %d\n", em.toChars(), ed.toChars(), isCEnum);
6227 em.ed = ed;
6228 if (isCEnum)
6230 /* C doesn't add the enum member to the symbol table of the enum tag, it adds
6231 * it to the symbol table that the tag is in. This is in contrast to D, where enum
6232 * members become members of the enum tag. To accommodate this, we add
6233 * the enum members to both symbol tables.
6235 em.addMember(sc, ed); // add em to ed's symbol table
6236 em.addMember(sc, sds); // add em to symbol table that ed is in
6237 em.parent = ed; // restore it after previous addMember() changed it
6239 else
6241 em.addMember(sc, isAnon ? sds : ed);
6247 /******************************************************
6248 * Verifies if the given Identifier is a DRuntime hook. It uses the hooks
6249 * defined in `id.d`.
6251 * Params:
6252 * id = Identifier to verify
6253 * Returns:
6254 * true if `id` is a DRuntime hook
6255 * false otherwise
6257 private bool isDRuntimeHook(Identifier id)
6259 return id == Id._d_HookTraceImpl ||
6260 id == Id._d_newclassT || id == Id._d_newclassTTrace ||
6261 id == Id._d_arraycatnTX || id == Id._d_arraycatnTXTrace ||
6262 id == Id._d_newThrowable || id == Id._d_delThrowable ||
6263 id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
6264 id == Id._d_arraysetassign || id == Id._d_arraysetctor ||
6265 id == Id._d_arrayctor ||
6266 id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT ||
6267 id == Id._d_arraysetlengthTTrace ||
6268 id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace ||
6269 id == Id._d_arrayappendcTX;
6272 void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList)
6274 //printf("[%s] TemplateInstance.dsymbolSemantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst.loc.toChars(), tempinst.toChars(), tempinst, global.gag, sc);
6275 version (none)
6277 for (Dsymbol s = tempinst; s; s = s.parent)
6279 printf("\t%s\n", s.toChars());
6281 printf("Scope\n");
6282 for (Scope* scx = sc; scx; scx = scx.enclosing)
6284 printf("\t%s parent %s\n", scx._module ? scx._module.toChars() : "null", scx.parent ? scx.parent.toChars() : "null");
6288 static if (LOG)
6290 printf("\n+TemplateInstance.dsymbolSemantic('%s', this=%p)\n", tempinst.toChars(), tempinst);
6292 if (tempinst.inst) // if semantic() was already run
6294 static if (LOG)
6296 printf("-TemplateInstance.dsymbolSemantic('%s', this=%p) already run\n",
6297 tempinst.inst.toChars(), tempinst.inst);
6299 return;
6301 if (tempinst.semanticRun != PASS.initial)
6303 static if (LOG)
6305 printf("Recursive template expansion\n");
6307 auto ungag = Ungag(global.gag);
6308 if (!tempinst.gagged)
6309 global.gag = 0;
6310 .error(tempinst.loc, "%s `%s` recursive template expansion", tempinst.kind, tempinst.toPrettyChars);
6311 if (tempinst.gagged)
6312 tempinst.semanticRun = PASS.initial;
6313 else
6314 tempinst.inst = tempinst;
6315 tempinst.errors = true;
6316 return;
6319 // Get the enclosing template instance from the scope tinst
6320 tempinst.tinst = sc.tinst;
6322 // Get the instantiating module from the scope minst
6323 tempinst.minst = sc.minst;
6324 // https://issues.dlang.org/show_bug.cgi?id=10920
6325 // If the enclosing function is non-root symbol,
6326 // this instance should be speculative.
6327 if (!tempinst.tinst && sc.func && sc.func.inNonRoot())
6329 tempinst.minst = null;
6332 tempinst.gagged = (global.gag > 0);
6334 tempinst.semanticRun = PASS.semantic;
6336 static if (LOG)
6338 printf("\tdo semantic\n");
6340 /* Find template declaration first,
6341 * then run semantic on each argument (place results in tiargs[]),
6342 * last find most specialized template from overload list/set.
6344 if (!tempinst.findTempDecl(sc, null) || !tempinst.semanticTiargs(sc) || !tempinst.findBestMatch(sc, argumentList))
6346 Lerror:
6347 if (tempinst.gagged)
6349 // https://issues.dlang.org/show_bug.cgi?id=13220
6350 // Roll back status for later semantic re-running
6351 tempinst.semanticRun = PASS.initial;
6353 else
6354 tempinst.inst = tempinst;
6355 tempinst.errors = true;
6356 return;
6358 TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration();
6359 assert(tempdecl);
6361 TemplateStats.incInstance(tempdecl, tempinst);
6363 tempdecl.checkDeprecated(tempinst.loc, sc);
6365 // If tempdecl is a mixin, disallow it
6366 if (tempdecl.ismixin)
6368 .error(tempinst.loc, "%s `%s` mixin templates are not regular templates", tempinst.kind, tempinst.toPrettyChars);
6369 goto Lerror;
6372 tempinst.hasNestedArgs(tempinst.tiargs, tempdecl.isstatic);
6373 if (tempinst.errors)
6374 goto Lerror;
6376 // Copy the tempdecl namespace (not the scope one)
6377 tempinst.cppnamespace = tempdecl.cppnamespace;
6378 if (tempinst.cppnamespace)
6379 tempinst.cppnamespace.dsymbolSemantic(sc);
6381 /* Greatly simplified semantic processing for AliasSeq templates
6383 if (tempdecl.isTrivialAliasSeq)
6385 tempinst.inst = tempinst;
6386 return aliasSeqInstanceSemantic(tempinst, sc, tempdecl);
6389 /* Greatly simplified semantic processing for Alias templates
6391 else if (tempdecl.isTrivialAlias)
6393 tempinst.inst = tempinst;
6394 return aliasInstanceSemantic(tempinst, sc, tempdecl);
6397 Expressions* fargs = argumentList.arguments; // TODO: resolve named args
6399 /* See if there is an existing TemplateInstantiation that already
6400 * implements the typeargs. If so, just refer to that one instead.
6402 tempinst.inst = tempdecl.findExistingInstance(tempinst, fargs);
6403 TemplateInstance errinst = null;
6404 if (!tempinst.inst)
6406 // So, we need to implement 'this' instance.
6408 else if (tempinst.inst.gagged && !tempinst.gagged && tempinst.inst.errors)
6410 // If the first instantiation had failed, re-run semantic,
6411 // so that error messages are shown.
6412 errinst = tempinst.inst;
6414 else
6416 // It's a match
6417 tempinst.parent = tempinst.inst.parent;
6418 tempinst.errors = tempinst.inst.errors;
6420 // If both this and the previous instantiation were gagged,
6421 // use the number of errors that happened last time.
6422 global.errors += tempinst.errors;
6423 global.gaggedErrors += tempinst.errors;
6425 // If the first instantiation was gagged, but this is not:
6426 if (tempinst.inst.gagged)
6428 // It had succeeded, mark it is a non-gagged instantiation,
6429 // and reuse it.
6430 tempinst.inst.gagged = tempinst.gagged;
6433 tempinst.tnext = tempinst.inst.tnext;
6434 tempinst.inst.tnext = tempinst;
6436 /* A module can have explicit template instance and its alias
6437 * in module scope (e,g, `alias Base64 = Base64Impl!('+', '/');`).
6438 * If the first instantiation 'inst' had happened in non-root module,
6439 * compiler can assume that its instantiated code would be included
6440 * in the separately compiled obj/lib file (e.g. phobos.lib).
6442 * However, if 'this' second instantiation happened in root module,
6443 * compiler might need to invoke its codegen
6444 * (https://issues.dlang.org/show_bug.cgi?id=2500 & https://issues.dlang.org/show_bug.cgi?id=2644).
6445 * But whole import graph is not determined until all semantic pass finished,
6446 * so 'inst' should conservatively finish the semantic3 pass for the codegen.
6448 if (tempinst.minst && tempinst.minst.isRoot() && !(tempinst.inst.minst && tempinst.inst.minst.isRoot()))
6450 /* Swap the position of 'inst' and 'this' in the instantiation graph.
6451 * Then, the primary instance `inst` will be changed to a root instance,
6452 * along with all members of `inst` having their scopes updated.
6454 * Before:
6455 * non-root -> A!() -> B!()[inst] -> C!() { members[non-root] }
6457 * root -> D!() -> B!()[this]
6459 * After:
6460 * non-root -> A!() -> B!()[this]
6462 * root -> D!() -> B!()[inst] -> C!() { members[root] }
6464 Module mi = tempinst.minst;
6465 TemplateInstance ti = tempinst.tinst;
6466 tempinst.minst = tempinst.inst.minst;
6467 tempinst.tinst = tempinst.inst.tinst;
6468 tempinst.inst.minst = mi;
6469 tempinst.inst.tinst = ti;
6471 /* https://issues.dlang.org/show_bug.cgi?id=21299
6472 `minst` has been updated on the primary instance `inst` so it is
6473 now coming from a root module, however all Dsymbol `inst.members`
6474 of the instance still have their `_scope.minst` pointing at the
6475 original non-root module. We must now propagate `minst` to all
6476 members so that forward referenced dependencies that get
6477 instantiated will also be appended to the root module, otherwise
6478 there will be undefined references at link-time. */
6479 extern (C++) final class InstMemberWalker : Visitor
6481 alias visit = Visitor.visit;
6482 TemplateInstance inst;
6484 extern (D) this(TemplateInstance inst) scope @safe
6486 this.inst = inst;
6489 override void visit(Dsymbol d)
6491 if (d._scope)
6492 d._scope.minst = inst.minst;
6495 override void visit(ScopeDsymbol sds)
6497 sds.members.foreachDsymbol( s => s.accept(this) );
6498 visit(cast(Dsymbol)sds);
6501 override void visit(AttribDeclaration ad)
6503 ad.include(null).foreachDsymbol( s => s.accept(this) );
6504 visit(cast(Dsymbol)ad);
6507 override void visit(ConditionalDeclaration cd)
6509 if (cd.condition.inc)
6510 visit(cast(AttribDeclaration)cd);
6511 else
6512 visit(cast(Dsymbol)cd);
6515 scope v = new InstMemberWalker(tempinst.inst);
6516 tempinst.inst.accept(v);
6518 if (!global.params.allInst &&
6519 tempinst.minst) // if inst was not speculative...
6521 assert(!tempinst.minst.isRoot()); // ... it was previously appended to a non-root module
6522 // Append again to the root module members[], so that the instance will
6523 // get codegen chances (depending on `tempinst.inst.needsCodegen()`).
6524 tempinst.inst.appendToModuleMember();
6527 assert(tempinst.inst.memberOf && tempinst.inst.memberOf.isRoot(), "no codegen chances");
6530 // modules imported by an existing instance should be added to the module
6531 // that instantiates the instance.
6532 if (tempinst.minst)
6533 foreach(imp; tempinst.inst.importedModules)
6534 if (!tempinst.minst.aimports.contains(imp))
6535 tempinst.minst.aimports.push(imp);
6537 static if (LOG)
6539 printf("\tit's a match with instance %p, %d\n", tempinst.inst, tempinst.inst.semanticRun);
6541 return;
6543 static if (LOG)
6545 printf("\timplement template instance %s '%s'\n", tempdecl.parent.toChars(), tempinst.toChars());
6546 printf("\ttempdecl %s\n", tempdecl.toChars());
6548 uint errorsave = global.errors;
6550 tempinst.inst = tempinst;
6551 tempinst.parent = tempinst.enclosing ? tempinst.enclosing : tempdecl.parent;
6552 //printf("parent = '%s'\n", parent.kind());
6554 TemplateStats.incUnique(tempdecl, tempinst);
6556 TemplateInstance tempdecl_instance_idx = tempdecl.addInstance(tempinst);
6558 //getIdent();
6560 // Store the place we added it to in target_symbol_list(_idx) so we can
6561 // remove it later if we encounter an error.
6562 Dsymbols* target_symbol_list = tempinst.appendToModuleMember();
6563 size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list.length - 1 : 0;
6565 // Copy the syntax trees from the TemplateDeclaration
6566 tempinst.members = Dsymbol.arraySyntaxCopy(tempdecl.members);
6568 // resolve TemplateThisParameter
6569 for (size_t i = 0; i < tempdecl.parameters.length; i++)
6571 if ((*tempdecl.parameters)[i].isTemplateThisParameter() is null)
6572 continue;
6573 Type t = isType((*tempinst.tiargs)[i]);
6574 assert(t);
6575 if (StorageClass stc = ModToStc(t.mod))
6577 //printf("t = %s, stc = x%llx\n", t.toChars(), stc);
6578 auto s = new Dsymbols();
6579 s.push(new StorageClassDeclaration(stc, tempinst.members));
6580 tempinst.members = s;
6582 break;
6585 // Create our own scope for the template parameters
6586 Scope* _scope = tempdecl._scope;
6587 if (tempdecl.semanticRun == PASS.initial)
6589 .error(tempinst.loc, "%s `%s` template instantiation `%s` forward references template declaration `%s`",
6590 tempinst.kind, tempinst.toPrettyChars, tempinst.toChars(), tempdecl.toChars());
6591 return;
6594 static if (LOG)
6596 printf("\tcreate scope for template parameters '%s'\n", tempinst.toChars());
6598 tempinst.argsym = new ScopeDsymbol();
6599 tempinst.argsym.parent = _scope.parent;
6600 _scope = _scope.push(tempinst.argsym);
6601 _scope.tinst = tempinst;
6602 _scope.minst = tempinst.minst;
6603 //scope.stc = 0;
6605 // Declare each template parameter as an alias for the argument type
6606 Scope* paramscope = _scope.push();
6607 paramscope.stc = 0;
6608 paramscope.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=14169
6609 // template parameters should be public
6610 tempinst.declareParameters(paramscope);
6611 paramscope.pop();
6613 // Add members of template instance to template instance symbol table
6614 //parent = scope.scopesym;
6615 tempinst.symtab = new DsymbolTable();
6617 tempinst.members.foreachDsymbol( (s)
6619 static if (LOG)
6621 printf("\t adding member '%s' %p kind %s to '%s'\n", s.toChars(), s, s.kind(), tempinst.toChars());
6623 s.addMember(_scope, tempinst);
6626 static if (LOG)
6628 printf("adding members done\n");
6631 /* See if there is only one member of template instance, and that
6632 * member has the same name as the template instance.
6633 * If so, this template instance becomes an alias for that member.
6635 //printf("members.length = %d\n", tempinst.members.length);
6636 if (tempinst.members.length)
6638 Dsymbol s;
6639 if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s)
6641 //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
6642 //printf("setting aliasdecl\n");
6643 tempinst.aliasdecl = s;
6647 /* If function template declaration
6649 if (fargs && tempinst.aliasdecl)
6651 if (auto fd = tempinst.aliasdecl.isFuncDeclaration())
6653 /* Transmit fargs to type so that TypeFunction.dsymbolSemantic() can
6654 * resolve any "auto ref" storage classes.
6656 if (fd.type)
6657 if (auto tf = fd.type.isTypeFunction())
6658 tf.fargs = fargs;
6662 // Do semantic() analysis on template instance members
6663 static if (LOG)
6665 printf("\tdo semantic() on template instance members '%s'\n", tempinst.toChars());
6667 Scope* sc2;
6668 sc2 = _scope.push(tempinst);
6669 //printf("enclosing = %d, sc.parent = %s\n", tempinst.enclosing, sc.parent.toChars());
6670 sc2.parent = tempinst;
6671 sc2.tinst = tempinst;
6672 sc2.minst = tempinst.minst;
6673 sc2.stc &= ~STC.deprecated_;
6674 tempinst.tryExpandMembers(sc2);
6676 tempinst.semanticRun = PASS.semanticdone;
6678 /* ConditionalDeclaration may introduce eponymous declaration,
6679 * so we should find it once again after semantic.
6681 if (tempinst.members.length)
6683 Dsymbol s;
6684 if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s)
6686 if (!tempinst.aliasdecl || tempinst.aliasdecl != s)
6688 //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
6689 //printf("setting aliasdecl 2\n");
6690 tempinst.aliasdecl = s;
6695 if (global.errors != errorsave)
6696 goto Laftersemantic;
6698 /* If any of the instantiation members didn't get semantic() run
6699 * on them due to forward references, we cannot run semantic2()
6700 * or semantic3() yet.
6703 bool found_deferred_ad = false;
6704 for (size_t i = 0; i < Module.deferred.length; i++)
6706 Dsymbol sd = Module.deferred[i];
6707 AggregateDeclaration ad = sd.isAggregateDeclaration();
6708 if (ad && ad.parent && ad.parent.isTemplateInstance())
6710 //printf("deferred template aggregate: %s %s\n",
6711 // sd.parent.toChars(), sd.toChars());
6712 found_deferred_ad = true;
6713 if (ad.parent == tempinst)
6715 ad.deferred = tempinst;
6716 break;
6720 if (found_deferred_ad || Module.deferred.length)
6721 goto Laftersemantic;
6724 /* The problem is when to parse the initializer for a variable.
6725 * Perhaps VarDeclaration.dsymbolSemantic() should do it like it does
6726 * for initializers inside a function.
6728 //if (sc.parent.isFuncDeclaration())
6730 /* https://issues.dlang.org/show_bug.cgi?id=782
6731 * this has problems if the classes this depends on
6732 * are forward referenced. Find a way to defer semantic()
6733 * on this template.
6735 tempinst.semantic2(sc2);
6737 if (global.errors != errorsave)
6738 goto Laftersemantic;
6740 if ((sc.func || (sc.flags & SCOPE.fullinst)) && !tempinst.tinst)
6742 /* If a template is instantiated inside function, the whole instantiation
6743 * should be done at that position. But, immediate running semantic3 of
6744 * dependent templates may cause unresolved forward reference.
6745 * https://issues.dlang.org/show_bug.cgi?id=9050
6746 * To avoid the issue, don't run semantic3 until semantic and semantic2 done.
6748 TemplateInstances deferred;
6749 tempinst.deferred = &deferred;
6751 //printf("Run semantic3 on %s\n", toChars());
6753 /* https://issues.dlang.org/show_bug.cgi?id=23965
6754 * DRuntime hooks are not deprecated, but may be used for deprecated
6755 * types. Deprecations are disabled while analysing hooks to avoid
6756 * spurious error messages.
6758 auto saveUseDeprecated = global.params.useDeprecated;
6759 if (sc.isDeprecated() && isDRuntimeHook(tempinst.name))
6760 global.params.useDeprecated = DiagnosticReporting.off;
6762 tempinst.trySemantic3(sc2);
6764 global.params.useDeprecated = saveUseDeprecated;
6766 for (size_t i = 0; i < deferred.length; i++)
6768 //printf("+ run deferred semantic3 on %s\n", deferred[i].toChars());
6769 deferred[i].semantic3(null);
6772 tempinst.deferred = null;
6774 else if (tempinst.tinst)
6776 bool doSemantic3 = false;
6777 FuncDeclaration fd;
6778 if (tempinst.aliasdecl)
6779 fd = tempinst.aliasdecl.toAlias2().isFuncDeclaration();
6781 if (fd)
6783 /* Template function instantiation should run semantic3 immediately
6784 * for attribute inference.
6786 scope fld = fd.isFuncLiteralDeclaration();
6787 if (fld && fld.tok == TOK.reserved)
6788 doSemantic3 = true;
6789 else if (sc.func)
6790 doSemantic3 = true;
6792 else if (sc.func)
6794 /* A lambda function in template arguments might capture the
6795 * instantiated scope context. For the correct context inference,
6796 * all instantiated functions should run the semantic3 immediately.
6797 * See also compilable/test14973.d
6799 foreach (oarg; tempinst.tdtypes)
6801 auto s = getDsymbol(oarg);
6802 if (!s)
6803 continue;
6805 if (auto td = s.isTemplateDeclaration())
6807 if (!td.literal)
6808 continue;
6809 assert(td.members && td.members.length == 1);
6810 s = (*td.members)[0];
6812 if (auto fld = s.isFuncLiteralDeclaration())
6814 if (fld.tok == TOK.reserved)
6816 doSemantic3 = true;
6817 break;
6821 //printf("[%s] %s doSemantic3 = %d\n", tempinst.tinst.loc.toChars(), tempinst.tinst.toChars(), doSemantic3);
6823 if (doSemantic3)
6824 tempinst.trySemantic3(sc2);
6826 TemplateInstance ti = tempinst.tinst;
6827 int nest = 0;
6828 while (ti && !ti.deferred && ti.tinst)
6830 ti = ti.tinst;
6831 if (++nest > global.recursionLimit)
6833 global.gag = 0; // ensure error message gets printed
6834 .error(tempinst.loc, "%s `%s` recursive expansion", tempinst.kind, tempinst.toPrettyChars);
6835 fatal();
6838 if (ti && ti.deferred)
6840 //printf("deferred semantic3 of %p %s, ti = %s, ti.deferred = %p\n", this, toChars(), ti.toChars());
6841 for (size_t i = 0;; i++)
6843 if (i == ti.deferred.length)
6845 ti.deferred.push(tempinst);
6846 break;
6848 if ((*ti.deferred)[i] == tempinst)
6849 break;
6854 if (tempinst.aliasdecl)
6856 /* https://issues.dlang.org/show_bug.cgi?id=13816
6857 * AliasDeclaration tries to resolve forward reference
6858 * twice (See inuse check in AliasDeclaration.toAlias()). It's
6859 * necessary to resolve mutual references of instantiated symbols, but
6860 * it will left a true recursive alias in tuple declaration - an
6861 * AliasDeclaration A refers TupleDeclaration B, and B contains A
6862 * in its elements. To correctly make it an error, we strictly need to
6863 * resolve the alias of eponymous member.
6865 tempinst.aliasdecl = tempinst.aliasdecl.toAlias2();
6867 // stop AliasAssign tuple building
6868 if (auto td = tempinst.aliasdecl.isTupleDeclaration())
6869 td.building = false;
6872 Laftersemantic:
6873 sc2.pop();
6874 _scope.pop();
6876 // Give additional context info if error occurred during instantiation
6877 if (global.errors != errorsave)
6879 if (!tempinst.errors)
6881 if (!tempdecl.literal)
6882 .error(tempinst.loc, "%s `%s` error instantiating", tempinst.kind, tempinst.toPrettyChars);
6883 if (tempinst.tinst)
6884 tempinst.tinst.printInstantiationTrace();
6886 tempinst.errors = true;
6887 if (tempinst.gagged)
6889 // Errors are gagged, so remove the template instance from the
6890 // instance/symbol lists we added it to and reset our state to
6891 // finish clean and so we can try to instantiate it again later
6892 // (see https://issues.dlang.org/show_bug.cgi?id=4302 and https://issues.dlang.org/show_bug.cgi?id=6602).
6893 tempdecl.removeInstance(tempdecl_instance_idx);
6894 if (target_symbol_list)
6896 // Because we added 'this' in the last position above, we
6897 // should be able to remove it without messing other indices up.
6898 assert((*target_symbol_list)[target_symbol_list_idx] == tempinst);
6899 target_symbol_list.remove(target_symbol_list_idx);
6900 tempinst.memberOf = null; // no longer a member
6902 tempinst.semanticRun = PASS.initial;
6903 tempinst.inst = null;
6904 tempinst.symtab = null;
6907 else if (errinst)
6909 /* https://issues.dlang.org/show_bug.cgi?id=14541
6910 * If the previous gagged instance had failed by
6911 * circular references, currrent "error reproduction instantiation"
6912 * might succeed, because of the difference of instantiated context.
6913 * On such case, the cached error instance needs to be overridden by the
6914 * succeeded instance.
6916 //printf("replaceInstance()\n");
6917 assert(errinst.errors);
6918 auto ti1 = TemplateInstanceBox(errinst);
6919 tempdecl.instances.remove(ti1);
6921 auto ti2 = TemplateInstanceBox(tempinst);
6922 tempdecl.instances[ti2] = tempinst;
6925 static if (LOG)
6927 printf("-TemplateInstance.dsymbolSemantic('%s', this=%p)\n", tempinst.toChars(), tempinst);
6931 /******************************************************
6932 * Do template instance semantic for isAliasSeq templates.
6933 * This is a greatly simplified version of templateInstanceSemantic().
6935 private
6936 void aliasSeqInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclaration tempdecl)
6938 //printf("[%s] aliasSeqInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
6939 Scope* paramscope = sc.push();
6940 paramscope.stc = 0;
6941 paramscope.visibility = Visibility(Visibility.Kind.public_);
6943 TemplateTupleParameter ttp = (*tempdecl.parameters)[0].isTemplateTupleParameter();
6944 Tuple va = tempinst.tdtypes[0].isTuple();
6945 Declaration d = new TupleDeclaration(tempinst.loc, ttp.ident, &va.objects);
6946 d.storage_class |= STC.templateparameter;
6947 d.dsymbolSemantic(sc);
6949 paramscope.pop();
6951 tempinst.aliasdecl = d;
6953 tempinst.semanticRun = PASS.semanticdone;
6956 /******************************************************
6957 * Do template instance semantic for isAlias templates.
6958 * This is a greatly simplified version of templateInstanceSemantic().
6960 private
6961 void aliasInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclaration tempdecl)
6963 //printf("[%s] aliasInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
6964 Scope* paramscope = sc.push();
6965 paramscope.stc = 0;
6966 paramscope.visibility = Visibility(Visibility.Kind.public_);
6968 TemplateTypeParameter ttp = (*tempdecl.parameters)[0].isTemplateTypeParameter();
6969 Type ta = tempinst.tdtypes[0].isType();
6970 auto ad = tempdecl.onemember.isAliasDeclaration();
6972 // Note: qualifiers can be in both 'ad.type.mod' and 'ad.storage_class'
6973 Declaration d = new AliasDeclaration(tempinst.loc, ttp.ident, ta.addMod(ad.type.mod));
6974 d.storage_class |= STC.templateparameter | ad.storage_class;
6975 d.dsymbolSemantic(sc);
6977 paramscope.pop();
6979 tempinst.aliasdecl = d;
6981 tempinst.semanticRun = PASS.semanticdone;
6984 // function used to perform semantic on AliasDeclaration
6985 void aliasSemantic(AliasDeclaration ds, Scope* sc)
6987 //printf("AliasDeclaration::semantic() %s\n", ds.toChars());
6989 // as DsymbolSemanticVisitor::visit(AliasDeclaration), in case we're called first.
6990 // see https://issues.dlang.org/show_bug.cgi?id=21001
6991 ds.storage_class |= sc.stc & STC.deprecated_;
6992 ds.visibility = sc.visibility;
6993 ds.userAttribDecl = sc.userAttribDecl;
6995 void normalRet()
6997 ds.inuse = 0;
6998 ds.semanticRun = PASS.semanticdone;
7000 if (auto sx = ds.overnext)
7002 ds.overnext = null;
7003 if (!ds.overloadInsert(sx))
7004 ScopeDsymbol.multiplyDefined(Loc.initial, sx, ds);
7008 void errorRet()
7010 ds.aliassym = null;
7011 ds.type = Type.terror;
7012 ds.inuse = 0;
7013 normalRet();
7016 // preserve the original type
7017 if (!ds.originalType && ds.type)
7018 ds.originalType = ds.type.syntaxCopy();
7020 if (ds.aliassym)
7022 auto fd = ds.aliassym.isFuncLiteralDeclaration();
7023 auto td = ds.aliassym.isTemplateDeclaration();
7024 if (fd || td && td.literal)
7026 if (fd && fd.semanticRun >= PASS.semanticdone)
7027 return normalRet();
7029 Expression e = new FuncExp(ds.loc, ds.aliassym);
7030 e = e.expressionSemantic(sc);
7031 if (auto fe = e.isFuncExp())
7033 ds.aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd;
7034 return normalRet();
7036 else
7037 return errorRet();
7040 if (ds.aliassym.isTemplateInstance())
7041 ds.aliassym.dsymbolSemantic(sc);
7042 return normalRet();
7044 ds.inuse = 1;
7046 // Given:
7047 // alias foo.bar.abc def;
7048 // it is not knowable from the syntax whether `def` is an alias
7049 // for type `foo.bar.abc` or an alias for symbol `foo.bar.abc`. It is up to the semantic()
7050 // pass to distinguish.
7051 // If it is a type, then `.type` is set and getType() will return that
7052 // type. If it is a symbol, then `.aliassym` is set and type is `null` -
7053 // toAlias() will return `.aliassym`
7055 const errors = global.errors;
7056 Type oldtype = ds.type;
7058 // Ungag errors when not instantiated DeclDefs scope alias
7059 auto ungag = Ungag(global.gag);
7060 //printf("%s parent = %s, gag = %d, instantiated = %d\n", ds.toChars(), ds.parent.toChars(), global.gag, ds.isInstantiated() !is null);
7061 if (ds.parent && global.gag && !ds.isInstantiated() && !ds.toParent2().isFuncDeclaration() && (sc.minst || sc.tinst))
7063 //printf("%s type = %s\n", ds.toPrettyChars(), ds.type.toChars());
7064 global.gag = 0;
7067 // https://issues.dlang.org/show_bug.cgi?id=18480
7068 // Detect `alias sym = sym;` to prevent creating loops in overload overnext lists.
7069 if (auto tident = ds.type.isTypeIdentifier())
7071 // Selective imports are allowed to alias to the same name `import mod : sym=sym`.
7072 if (!ds._import)
7074 if (tident.ident is ds.ident && !tident.idents.length)
7076 error(ds.loc, "`alias %s = %s;` cannot alias itself, use a qualified name to create an overload set",
7077 ds.ident.toChars(), tident.ident.toChars());
7078 ds.type = Type.terror;
7082 /* This section is needed because Type.resolve() will:
7083 * const x = 3;
7084 * alias y = x;
7085 * try to convert identifier x to 3.
7087 auto s = ds.type.toDsymbol(sc);
7088 if (errors != global.errors)
7089 return errorRet();
7090 if (s == ds)
7092 .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
7093 return errorRet();
7095 if (!s || !s.isEnumMember())
7097 Type t;
7098 Expression e;
7099 Scope* sc2 = sc;
7100 if (ds.storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.disable))
7102 // For 'ref' to be attached to function types, and picked
7103 // up by Type.resolve(), it has to go into sc.
7104 sc2 = sc.push();
7105 sc2.stc |= ds.storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
7107 ds.type = ds.type.addSTC(ds.storage_class);
7108 ds.type.resolve(ds.loc, sc2, e, t, s);
7109 if (sc2 != sc)
7110 sc2.pop();
7112 if (e) // Try to convert Expression to Dsymbol
7114 // TupleExp is naturally converted to a TupleDeclaration
7115 if (auto te = e.isTupleExp())
7116 s = new TupleDeclaration(te.loc, ds.ident, cast(Objects*)te.exps);
7117 else
7119 s = getDsymbol(e);
7120 if (!s)
7122 if (e.op != EXP.error)
7123 .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
7124 return errorRet();
7128 ds.type = t;
7130 if (s == ds)
7132 assert(global.errors);
7133 return errorRet();
7135 if (s) // it's a symbolic alias
7137 //printf("alias %s resolved to %s %s\n", ds.toChars(), s.kind(), s.toChars());
7138 ds.type = null;
7139 ds.aliassym = s;
7141 else // it's a type alias
7143 //printf("alias %s resolved to type %s\n", ds.toChars(), ds.type.toChars());
7144 ds.type = ds.type.typeSemantic(ds.loc, sc);
7145 ds.aliassym = null;
7148 if (global.gag && errors != global.errors)
7149 return errorRet();
7151 normalRet();
7154 /********************
7155 * Perform semantic on AliasAssignment.
7156 * Has a lot of similarities to aliasSemantic(). Perhaps they should share code.
7158 private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
7160 //printf("AliasAssign::semantic() %p, %s\n", ds, ds.ident.toChars());
7162 void errorRet()
7164 ds.errors = true;
7165 ds.type = Type.terror;
7166 ds.semanticRun = PASS.semanticdone;
7167 return;
7170 /* Find the AliasDeclaration corresponding to ds.
7171 * Returns: AliasDeclaration if found, null if error
7173 AliasDeclaration findAliasDeclaration(AliasAssign ds, Scope* sc)
7175 Dsymbol scopesym;
7176 Dsymbol as = sc.search(ds.loc, ds.ident, &scopesym);
7177 if (!as)
7179 .error(ds.loc, "%s `%s` undefined identifier `%s`", ds.kind, ds.toPrettyChars, ds.ident.toChars());
7180 return null;
7182 if (as.errors)
7183 return null;
7185 auto ad = as.isAliasDeclaration();
7186 if (!ad)
7188 .error(ds.loc, "%s `%s` identifier `%s` must be an alias declaration", ds.kind, ds.toPrettyChars, as.toChars());
7189 return null;
7192 if (ad.overnext)
7194 error(ds.loc, "%s `%s` cannot reassign overloaded alias", ds.kind, ds.toPrettyChars);
7195 return null;
7198 // Check constraints on the parent
7199 auto adParent = ad.toParent();
7200 if (adParent != ds.toParent())
7202 if (!adParent)
7203 adParent = ds.toParent();
7204 .error(ds.loc, "`%s` must have same parent `%s` as alias `%s`", ds.ident.toChars(), adParent.toChars(), ad.toChars());
7205 return null;
7207 if (!adParent.isTemplateInstance())
7209 .error(ds.loc, "%s `%s` must be a member of a template", ds.kind, ds.toPrettyChars);
7210 return null;
7213 return ad;
7216 auto aliassym = findAliasDeclaration(ds, sc);
7217 if (!aliassym)
7218 return errorRet();
7220 if (aliassym.adFlags & Declaration.wasRead)
7222 if (!aliassym.errors)
7223 error(ds.loc, "%s was read, so cannot reassign", aliassym.toChars());
7224 aliassym.errors = true;
7225 return errorRet();
7228 aliassym.adFlags |= Declaration.ignoreRead; // temporarilly allow reads of aliassym
7230 const storage_class = sc.stc & (STC.deprecated_ | STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
7232 if (ds.aliassym)
7234 auto fd = ds.aliassym.isFuncLiteralDeclaration();
7235 auto td = ds.aliassym.isTemplateDeclaration();
7236 if (fd && fd.semanticRun >= PASS.semanticdone)
7239 else if (fd || td && td.literal)
7242 Expression e = new FuncExp(ds.loc, ds.aliassym);
7243 e = e.expressionSemantic(sc);
7244 auto fe = e.isFuncExp();
7245 if (!fe)
7246 return errorRet();
7247 ds.aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd;
7249 else if (ds.aliassym.isTemplateInstance())
7250 ds.aliassym.dsymbolSemantic(sc);
7252 aliassym.type = null;
7253 aliassym.aliassym = ds.aliassym;
7254 return;
7257 /* Given:
7258 * abc = def;
7259 * it is not knownable from the syntax whether `def` is a type or a symbol.
7260 * It appears here as `ds.type`. Do semantic analysis on `def` to disambiguate.
7263 const errors = global.errors;
7264 Dsymbol s;
7266 // Try AliasSeq optimization
7267 if (auto ti = ds.type.isTypeInstance())
7269 if (!ti.tempinst.findTempDecl(sc, null))
7270 return errorRet();
7271 if (auto tempinst = isAliasSeq(sc, ti))
7273 s = aliasAssignInPlace(sc, tempinst, aliassym);
7274 if (!s)
7275 return errorRet();
7276 goto Lsymdone;
7280 /* This section is needed because Type.resolve() will:
7281 * const x = 3;
7282 * alias y = x;
7283 * try to convert identifier x to 3.
7285 s = ds.type.toDsymbol(sc);
7286 if (errors != global.errors)
7287 return errorRet();
7288 if (s == aliassym)
7290 .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
7291 return errorRet();
7294 if (!s || !s.isEnumMember())
7296 Type t;
7297 Expression e;
7298 Scope* sc2 = sc;
7299 if (storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable))
7301 // For 'ref' to be attached to function types, and picked
7302 // up by Type.resolve(), it has to go into sc.
7303 sc2 = sc.push();
7304 sc2.stc |= storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
7306 ds.type = ds.type.addSTC(storage_class);
7307 ds.type.resolve(ds.loc, sc2, e, t, s);
7308 if (sc2 != sc)
7309 sc2.pop();
7311 if (e) // Try to convert Expression to Dsymbol
7313 // TupleExp is naturally converted to a TupleDeclaration
7314 if (auto te = e.isTupleExp())
7315 s = new TupleDeclaration(te.loc, ds.ident, cast(Objects*)te.exps);
7316 else
7318 s = getDsymbol(e);
7319 if (!s)
7321 if (e.op != EXP.error)
7322 .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
7323 return errorRet();
7327 ds.type = t;
7329 if (s == aliassym)
7331 assert(global.errors);
7332 return errorRet();
7335 if (s) // it's a symbolic alias
7337 Lsymdone:
7338 //printf("alias %s resolved to %s %s\n", toChars(), s.kind(), s.toChars());
7339 aliassym.type = null;
7340 aliassym.aliassym = s;
7341 aliassym.storage_class |= sc.stc & STC.deprecated_;
7342 aliassym.visibility = sc.visibility;
7343 aliassym.userAttribDecl = sc.userAttribDecl;
7345 else // it's a type alias
7347 //printf("alias %s resolved to type %s\n", toChars(), type.toChars());
7348 aliassym.type = ds.type.typeSemantic(ds.loc, sc);
7349 aliassym.aliassym = null;
7353 aliassym.adFlags &= ~Declaration.ignoreRead;
7355 if (aliassym.type && aliassym.type.ty == Terror ||
7356 global.gag && errors != global.errors)
7358 aliassym.type = Type.terror;
7359 aliassym.aliassym = null;
7360 return errorRet();
7363 ds.semanticRun = PASS.semanticdone;
7366 /***************************************
7367 * Expands template instance arguments inside 'alias assign' target declaration (aliassym),
7368 * instead of inside 'tempinst.tiargs' every time.
7369 * Params:
7370 * tempinst = AliasSeq instance
7371 * aliassym = the AliasDeclaration corresponding to AliasAssign
7372 * Returns:
7373 * null.
7375 private TupleDeclaration aliasAssignInPlace(Scope* sc, TemplateInstance tempinst,
7376 AliasDeclaration aliassym)
7378 // Mark instance with semantic done, not needed but just in case.
7379 tempinst.inst = tempinst;
7380 tempinst.semanticRun = PASS.semanticdone;
7381 TupleDeclaration td;
7382 if (aliassym.type)
7384 // Convert TypeTuple to TupleDeclaration to avoid back and forth allocations
7385 // in the assignment process
7386 if (auto tt = aliassym.type.isTypeTuple())
7388 auto objs = new Objects(tt.arguments.length);
7389 foreach (i, p; *tt.arguments)
7390 (*objs)[i] = p.type;
7391 td = new TupleDeclaration(tempinst.loc, aliassym.ident, objs);
7392 td.storage_class |= STC.templateparameter;
7393 td.building = true;
7394 aliassym.type = null;
7396 else if (aliassym.type.isTypeError())
7397 return null;
7400 else if (auto otd = aliassym.aliassym.isTupleDeclaration())
7402 if (otd.building)
7403 td = otd;
7404 else
7406 td = new TupleDeclaration(tempinst.loc, aliassym.ident, otd.objects.copy());
7407 td.storage_class |= STC.templateparameter;
7408 td.building = true;
7411 // If starting from single element in aliassym (td == null) we need to build the tuple
7412 // after semanticTiargs to keep same semantics (for example a FuncLiteraldeclaration
7413 // template argument is converted to FuncExp)
7414 if (td)
7415 aliassym.aliassym = td;
7416 aliassym.semanticRun = PASS.semanticdone;
7417 if (!TemplateInstance.semanticTiargs(tempinst.loc, sc, tempinst.tiargs, 0, td))
7419 tempinst.errors = true;
7420 return null;
7422 // The alias will stop tuple 'building' mode when used (in AliasDeclaration.toAlias(),
7423 // then TupleDeclaration.getType() will work again)
7424 aliassym.semanticRun = PASS.initial;
7425 if (!td)
7427 td = new TupleDeclaration(tempinst.loc, aliassym.ident, tempinst.tiargs);
7428 td.storage_class |= STC.templateparameter;
7429 td.building = true;
7430 return td;
7433 auto tiargs = tempinst.tiargs;
7434 size_t oldlen = td.objects.length;
7435 size_t origstart;
7436 size_t insertidx;
7437 size_t insertlen;
7438 foreach (i, o; *tiargs)
7440 if (o !is td)
7442 ++insertlen;
7443 continue;
7445 // tuple contains itself (tuple = AliasSeq!(..., tuple, ...))
7446 if (insertlen) // insert any left element before
7448 td.objects.insert(insertidx, (*tiargs)[i - insertlen .. i]);
7449 if (insertidx == 0) // reset original tuple start point
7450 origstart = insertlen;
7451 insertlen = 0;
7453 if (insertidx) // insert tuple if found more than one time
7455 td.objects.reserve(oldlen); // reserve first to assert a valid slice
7456 td.objects.pushSlice((*td.objects)[origstart .. origstart + oldlen]);
7458 insertidx = td.objects.length;
7460 if (insertlen)
7462 if (insertlen != tiargs.length) // insert any left element
7463 td.objects.pushSlice((*tiargs)[$ - insertlen .. $]);
7464 else
7465 // just assign tiargs if tuple = AliasSeq!(nottuple, nottuple...)
7466 td.objects = tempinst.tiargs;
7468 return td;
7471 /***************************************
7472 * Check if a template instance is a trivial AliasSeq but without other overloads.
7473 * We can only be 100% sure of being AliasSeq after running semanticTiargs()
7474 * and findBestMatch() but this optimization must happen before that.
7476 private TemplateInstance isAliasSeq(Scope* sc, TypeInstance ti)
7478 auto tovers = ti.tempinst.tempdecl.isOverloadSet();
7479 foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
7481 Dsymbol dstart = tovers ? tovers.a[oi] : ti.tempinst.tempdecl;
7482 int r = overloadApply(dstart, (Dsymbol s)
7484 auto td = s.isTemplateDeclaration();
7485 if (!td || !td.isTrivialAliasSeq)
7486 return 1;
7487 return 0;
7489 if (r)
7490 return null;
7492 return ti.tempinst;
7495 /***************************************
7496 * Find all instance fields in `ad`, then push them into `fields`.
7498 * Runs semantic() for all instance field variables, but also
7499 * the field types can remain yet not resolved forward references,
7500 * except direct recursive definitions.
7501 * After the process sizeok is set to Sizeok.fwd.
7503 * Params:
7504 * ad = the AggregateDeclaration to examine
7505 * Returns:
7506 * false if any errors occur.
7508 bool determineFields(AggregateDeclaration ad)
7510 if (ad._scope)
7511 dsymbolSemantic(ad, null);
7512 if (ad.sizeok != Sizeok.none)
7513 return true;
7515 //printf("determineFields() %s, fields.length = %d\n", toChars(), fields.length);
7516 // determineFields can be called recursively from one of the fields's v.semantic
7517 ad.fields.setDim(0);
7519 static int func(Dsymbol s, void* ctx)
7521 auto ad = cast(AggregateDeclaration)ctx;
7522 auto v = s.isVarDeclaration();
7523 if (!v)
7524 return 0;
7525 if (v.storage_class & STC.manifest)
7526 return 0;
7528 if (v.semanticRun < PASS.semanticdone)
7529 v.dsymbolSemantic(null);
7530 // Return in case a recursive determineFields triggered by v.semantic already finished
7531 if (ad.sizeok != Sizeok.none)
7532 return 1;
7534 if (v.aliasTuple)
7536 // If this variable was really a tuple, process each element.
7537 return v.aliasTuple.foreachVar(tv => tv.apply(&func, cast(void*) ad));
7540 if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter))
7541 return 0;
7542 if (!v.isField() || v.semanticRun < PASS.semanticdone)
7543 return 1; // unresolvable forward reference
7545 ad.fields.push(v);
7547 if (v.storage_class & STC.ref_)
7548 return 0;
7549 auto tv = v.type.baseElemOf();
7550 if (auto tvs = tv.isTypeStruct())
7552 if (ad == tvs.sym)
7554 const(char)* psz = (v.type.toBasetype().ty == Tsarray) ? "static array of " : "";
7555 .error(ad.loc, "%s `%s` cannot have field `%s` with %ssame struct type", ad.kind, ad.toPrettyChars, v.toChars(), psz);
7556 ad.type = Type.terror;
7557 ad.errors = true;
7558 return 1;
7561 return 0;
7564 if (ad.members)
7566 for (size_t i = 0; i < ad.members.length; i++)
7568 auto s = (*ad.members)[i];
7569 if (s.apply(&func, cast(void *)ad))
7571 if (ad.sizeok != Sizeok.none)
7573 // recursive determineFields already finished
7574 return true;
7576 return false;
7581 if (ad.sizeok != Sizeok.done)
7582 ad.sizeok = Sizeok.fwd;
7584 return true;
7587 /// Do an atomic operation (currently tailored to [shared] static ctors|dtors) needs
7588 private CallExp doAtomicOp (string op, Identifier var, Expression arg)
7590 assert(op == "-=" || op == "+=");
7592 Module mod = Module.loadCoreAtomic();
7593 if (!mod)
7594 return null; // core.atomic couldn't be loaded
7596 const loc = Loc.initial;
7598 Objects* tiargs = new Objects(1);
7599 (*tiargs)[0] = new StringExp(loc, op);
7601 Expressions* args = new Expressions(2);
7602 (*args)[0] = new IdentifierExp(loc, var);
7603 (*args)[1] = arg;
7605 auto sc = new ScopeExp(loc, mod);
7606 auto dti = new DotTemplateInstanceExp(
7607 loc, sc, Id.atomicOp, tiargs);
7609 return CallExp.create(loc, dti, args);
7612 /***************************************
7613 * Interpret a `pragma(inline, x)`
7615 * Params:
7616 * loc = location for error messages
7617 * sc = scope for evaluation of argument
7618 * args = pragma arguments
7619 * Returns: corresponding `PINLINE` state
7621 PINLINE evalPragmaInline(Loc loc, Scope* sc, Expressions* args)
7623 if (!args || args.length == 0)
7624 return PINLINE.default_;
7626 if (args && args.length > 1)
7628 .error(loc, "one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) args.length);
7629 args.setDim(1);
7630 (*args)[0] = ErrorExp.get();
7633 Expression e = (*args)[0];
7634 if (!e.type)
7636 sc = sc.startCTFE();
7637 e = e.expressionSemantic(sc);
7638 e = resolveProperties(sc, e);
7639 sc = sc.endCTFE();
7640 e = e.ctfeInterpret();
7641 e = e.toBoolean(sc);
7642 if (e.isErrorExp())
7643 .error(loc, "pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars());
7644 (*args)[0] = e;
7647 const opt = e.toBool();
7648 if (opt.isEmpty())
7649 return PINLINE.default_;
7650 else if (opt.get())
7651 return PINLINE.always;
7652 else
7653 return PINLINE.never;
7656 /***************************************************
7657 * Set up loc for a parse of a mixin. Append the input text to the mixin.
7658 * Params:
7659 * input = mixin text
7660 * loc = location to adjust
7661 * mixinOut = sink for mixin text data
7662 * Returns:
7663 * adjusted loc suitable for Parser
7666 Loc adjustLocForMixin(const(char)[] input, ref const Loc loc, ref Output mixinOut)
7668 Loc result;
7669 if (mixinOut.doOutput)
7671 const lines = mixinOut.bufferLines;
7672 writeMixin(input, loc, mixinOut.bufferLines, *mixinOut.buffer);
7673 result = Loc(mixinOut.name.ptr, lines + 2, loc.charnum);
7675 else if (loc.filename)
7677 /* Create a pseudo-filename for the mixin string, as it may not even exist
7678 * in the source file.
7680 auto len = strlen(loc.filename) + 7 + (loc.linnum).sizeof * 3 + 1;
7681 char* filename = cast(char*)mem.xmalloc(len);
7682 snprintf(filename, len, "%s-mixin-%d", loc.filename, cast(int)loc.linnum);
7683 result = Loc(filename, loc.linnum, loc.charnum);
7685 else
7686 result = loc;
7687 return result;
7690 /**************************************
7691 * Append source code text to output for better debugging.
7692 * Canonicalize line endings.
7693 * Params:
7694 * s = source code text
7695 * loc = location of source code text
7696 * lines = line count to update
7697 * output = sink for output
7699 private void writeMixin(const(char)[] s, ref const Loc loc, ref int lines, ref OutBuffer buf)
7701 buf.writestring("// expansion at ");
7702 buf.writestring(loc.toChars());
7703 buf.writenl();
7705 ++lines;
7707 // write by line to create consistent line endings
7708 size_t lastpos = 0;
7709 for (size_t i = 0; i < s.length; ++i)
7711 // detect LF and CRLF
7712 const c = s[i];
7713 if (c == '\n' || (c == '\r' && i+1 < s.length && s[i+1] == '\n'))
7715 buf.writestring(s[lastpos .. i]);
7716 buf.writenl();
7717 ++lines;
7718 if (c == '\r')
7719 ++i;
7720 lastpos = i + 1;
7724 if(lastpos < s.length)
7725 buf.writestring(s[lastpos .. $]);
7727 if (s.length == 0 || s[$-1] != '\n')
7729 buf.writenl(); // ensure empty line after expansion
7730 ++lines;
7732 buf.writenl();
7733 ++lines;
7737 * Check signature of `pragma(printf)` function, print error if invalid.
7739 * printf/scanf-like functions must be of the form:
7740 * extern (C/C++) T printf([parameters...], const(char)* format, ...);
7741 * or:
7742 * extern (C/C++) T vprintf([parameters...], const(char)* format, va_list);
7744 * Params:
7745 * funcdecl = function to check
7746 * f = function type
7747 * sc = scope
7749 void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope* sc)
7751 static bool isPointerToChar(Parameter p)
7753 if (auto tptr = p.type.isTypePointer())
7755 return tptr.next.ty == Tchar;
7757 return false;
7760 bool isVa_list(Parameter p)
7762 return p.type.equals(target.va_listType(funcdecl.loc, sc));
7765 const nparams = f.parameterList.length;
7766 const p = (funcdecl.printf ? Id.printf : Id.scanf).toChars();
7767 if (!(f.linkage == LINK.c || f.linkage == LINK.cpp))
7769 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have `extern(C)` or `extern(C++)` linkage,"
7770 ~" not `extern(%s)`",
7771 p, funcdecl.toChars(), f.linkage.linkageToChars());
7773 if (f.parameterList.varargs == VarArg.variadic)
7775 if (!(nparams >= 1 && isPointerToChar(f.parameterList[nparams - 1])))
7777 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have"
7778 ~ " signature `%s %s([parameters...], const(char)*, ...)` not `%s`",
7779 p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars(), funcdecl.type.toChars());
7782 else if (f.parameterList.varargs == VarArg.none)
7784 if(!(nparams >= 2 && isPointerToChar(f.parameterList[nparams - 2]) &&
7785 isVa_list(f.parameterList[nparams - 1])))
7786 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have"~
7787 " signature `%s %s([parameters...], const(char)*, va_list)`",
7788 p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars());
7790 else
7792 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have C-style variadic `...` or `va_list` parameter",
7793 p, funcdecl.toChars());
7797 /*********************************************
7798 * Search for ident as member of d.
7799 * Params:
7800 * d = dsymbol where ident is searched for
7801 * loc = location to print for error messages
7802 * ident = identifier to search for
7803 * flags = IgnoreXXXX
7804 * Returns:
7805 * null if not found
7807 extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int flags = IgnoreNone)
7809 scope v = new SearchVisitor(loc, ident, flags);
7810 d.accept(v);
7811 return v.result;
7814 private extern(C++) class SearchVisitor : Visitor
7816 alias visit = Visitor.visit;
7818 const Loc loc;
7819 Identifier ident;
7820 int flags;
7821 Dsymbol result;
7823 this(const ref Loc loc, Identifier ident, int flags)
7825 this.loc = loc;
7826 this.ident = ident;
7827 this.flags = flags;
7830 void setResult(Dsymbol d)
7832 result = d;
7835 override void visit(Dsymbol d)
7837 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", d, d.toChars(), ident.toChars());
7838 return setResult(null);
7841 override void visit(ScopeDsymbol sds)
7843 //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", sds.toChars(), ident.toChars(), flags);
7844 //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
7846 // Look in symbols declared in this module
7847 if (sds.symtab && !(flags & SearchImportsOnly))
7849 //printf(" look in locals\n");
7850 auto s1 = sds.symtab.lookup(ident);
7851 if (s1)
7853 //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
7854 return setResult(s1);
7857 //printf(" not found in locals\n");
7859 // Look in imported scopes
7860 if (!sds.importedScopes)
7861 return setResult(null);
7863 //printf(" look in imports\n");
7864 Dsymbol s = null;
7865 OverloadSet a = null;
7866 // Look in imported modules
7867 for (size_t i = 0; i < sds.importedScopes.length; i++)
7869 // If private import, don't search it
7870 if ((flags & IgnorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_)
7871 continue;
7872 int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches
7873 Dsymbol ss = (*sds.importedScopes)[i];
7874 //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
7876 if (ss.isModule())
7878 if (flags & SearchLocalsOnly)
7879 continue;
7881 else // mixin template
7883 if (flags & SearchImportsOnly)
7884 continue;
7886 sflags |= SearchLocalsOnly;
7889 /* Don't find private members if ss is a module
7891 Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone));
7892 import dmd.access : symbolIsVisible;
7893 if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(sds, s2))
7894 continue;
7895 if (!s)
7897 s = s2;
7898 if (s && s.isOverloadSet())
7899 a = sds.mergeOverloadSet(ident, a, s);
7901 else if (s2 && s != s2)
7903 if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
7905 /* After following aliases, we found the same
7906 * symbol, so it's not an ambiguity. But if one
7907 * alias is deprecated or less accessible, prefer
7908 * the other.
7910 if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
7911 s = s2;
7913 else
7915 /* Two imports of the same module should be regarded as
7916 * the same.
7918 Import i1 = s.isImport();
7919 Import i2 = s2.isImport();
7920 if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
7922 /* https://issues.dlang.org/show_bug.cgi?id=8668
7923 * Public selective import adds AliasDeclaration in module.
7924 * To make an overload set, resolve aliases in here and
7925 * get actual overload roots which accessible via s and s2.
7927 s = s.toAlias();
7928 s2 = s2.toAlias();
7929 /* If both s2 and s are overloadable (though we only
7930 * need to check s once)
7933 auto so2 = s2.isOverloadSet();
7934 if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
7936 if (symbolIsVisible(sds, s2))
7938 a = sds.mergeOverloadSet(ident, a, s2);
7940 if (!symbolIsVisible(sds, s))
7941 s = s2;
7942 continue;
7945 /* Two different overflow sets can have the same members
7946 * https://issues.dlang.org/show_bug.cgi?id=16709
7948 auto so = s.isOverloadSet();
7949 if (so && so2)
7951 if (so.a.length == so2.a.length)
7953 foreach (j; 0 .. so.a.length)
7955 if (so.a[j] !is so2.a[j])
7956 goto L1;
7958 continue; // the same
7960 { } // different
7964 if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
7965 return setResult(null);
7967 /* If two imports from C import files, pick first one, as C has global name space
7969 if (s.isCsymbol() && s2.isCsymbol())
7970 continue;
7972 if (!(flags & IgnoreErrors))
7973 ScopeDsymbol.multiplyDefined(loc, s, s2);
7974 break;
7979 if (s)
7981 /* Build special symbol if we had multiple finds
7983 if (a)
7985 if (!s.isOverloadSet())
7986 a = sds.mergeOverloadSet(ident, a, s);
7987 s = a;
7989 //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
7990 return setResult(s);
7992 //printf(" not found in imports\n");
7993 return setResult(null);
7996 override void visit(WithScopeSymbol ws)
7998 //printf("WithScopeSymbol.search(%s)\n", ident.toChars());
7999 if (flags & SearchImportsOnly)
8000 return setResult(null);
8001 // Acts as proxy to the with class declaration
8002 Dsymbol s = null;
8003 Expression eold = null;
8004 for (Expression e = ws.withstate.exp; e && e != eold; e = resolveAliasThis(ws._scope, e, true))
8006 if (auto se = e.isScopeExp())
8008 s = se.sds;
8010 else if (e.isTypeExp())
8012 s = e.type.toDsymbol(null);
8014 else
8016 Type t = e.type.toBasetype();
8017 s = t.toDsymbol(null);
8019 if (s)
8021 s = s.search(loc, ident, flags);
8022 if (s)
8023 return setResult(s);
8025 eold = e;
8027 return setResult(null);
8030 override void visit(ArrayScopeSymbol ass)
8032 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
8033 if (ident != Id.dollar)
8034 return setResult(null);
8036 VarDeclaration* pvar;
8037 Expression ce;
8039 static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
8042 /* $ gives the number of type entries in the type tuple
8044 auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
8045 Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
8046 v._init = new ExpInitializer(Loc.initial, e);
8047 v.storage_class |= STC.temp | STC.static_ | STC.const_;
8048 v.dsymbolSemantic(sc);
8049 return v;
8052 const DYNCAST kind = ass.arrayContent.dyncast();
8053 switch (kind) with (DYNCAST)
8055 case dsymbol:
8056 TupleDeclaration td = cast(TupleDeclaration) ass.arrayContent;
8057 /* $ gives the number of elements in the tuple
8059 auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
8060 Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
8061 v._init = new ExpInitializer(Loc.initial, e);
8062 v.storage_class |= STC.temp | STC.static_ | STC.const_;
8063 v.dsymbolSemantic(ass._scope);
8064 return setResult(v);
8065 case type:
8066 return setResult(dollarFromTypeTuple(loc, cast(TypeTuple) ass.arrayContent, ass._scope));
8067 default:
8068 break;
8070 Expression exp = cast(Expression) ass.arrayContent;
8071 if (auto ie = exp.isIndexExp())
8073 /* array[index] where index is some function of $
8075 pvar = &ie.lengthVar;
8076 ce = ie.e1;
8078 else if (auto se = exp.isSliceExp())
8080 /* array[lwr .. upr] where lwr or upr is some function of $
8082 pvar = &se.lengthVar;
8083 ce = se.e1;
8085 else if (auto ae = exp.isArrayExp())
8087 /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
8088 * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
8090 pvar = &ae.lengthVar;
8091 ce = ae.e1;
8093 else
8095 /* Didn't find $, look in enclosing scope(s).
8097 return setResult(null);
8099 ce = ce.lastComma();
8100 /* If we are indexing into an array that is really a type
8101 * tuple, rewrite this as an index into a type tuple and
8102 * try again.
8104 if (auto te = ce.isTypeExp())
8106 if (auto ttp = te.type.isTypeTuple())
8107 return setResult(dollarFromTypeTuple(loc, ttp, ass._scope));
8109 /* *pvar is lazily initialized, so if we refer to $
8110 * multiple times, it gets set only once.
8112 if (!*pvar) // if not already initialized
8114 /* Create variable v and set it to the value of $
8116 VarDeclaration v;
8117 Type t;
8118 if (auto tupexp = ce.isTupleExp())
8120 /* It is for an expression tuple, so the
8121 * length will be a const.
8123 Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
8124 v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
8125 v.storage_class |= STC.temp | STC.static_ | STC.const_;
8127 else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
8129 // Look for opDollar
8130 assert(exp.op == EXP.array || exp.op == EXP.slice);
8131 AggregateDeclaration ad = isAggregate(t);
8132 assert(ad);
8133 Dsymbol s = ad.search(loc, Id.opDollar);
8134 if (!s) // no dollar exists -- search in higher scope
8135 return setResult(null);
8136 s = s.toAlias();
8137 Expression e = null;
8138 // Check for multi-dimensional opDollar(dim) template.
8139 if (TemplateDeclaration td = s.isTemplateDeclaration())
8141 dinteger_t dim = 0;
8142 if (auto ae = exp.isArrayExp())
8144 dim = ae.currentDimension;
8146 else if (exp.isSliceExp())
8148 dim = 0; // slices are currently always one-dimensional
8150 else
8152 assert(0);
8154 auto tiargs = new Objects();
8155 Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
8156 edim = edim.expressionSemantic(ass._scope);
8157 tiargs.push(edim);
8158 e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
8160 else
8162 /* opDollar exists, but it's not a template.
8163 * This is acceptable ONLY for single-dimension indexing.
8164 * Note that it's impossible to have both template & function opDollar,
8165 * because both take no arguments.
8167 auto ae = exp.isArrayExp();
8168 if (ae && ae.arguments.length != 1)
8170 error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
8171 return setResult(null);
8173 Declaration d = s.isDeclaration();
8174 assert(d);
8175 e = new DotVarExp(loc, ce, d);
8177 e = e.expressionSemantic(ass._scope);
8178 if (!e.type)
8179 error(exp.loc, "`%s` has no value", e.toChars());
8180 t = e.type.toBasetype();
8181 if (t && t.ty == Tfunction)
8182 e = new CallExp(e.loc, e);
8183 v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
8184 v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
8186 else
8188 /* For arrays, $ will either be a compile-time constant
8189 * (in which case its value in set during constant-folding),
8190 * or a variable (in which case an expression is created in
8191 * toir.c).
8194 // https://issues.dlang.org/show_bug.cgi?id=16213
8195 // For static arrays $ is known at compile time,
8196 // so declare it as a manifest constant.
8197 auto tsa = ce.type ? ce.type.isTypeSArray() : null;
8198 if (tsa)
8200 auto e = new ExpInitializer(loc, tsa.dim);
8201 v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
8203 else
8205 auto e = new VoidInitializer(Loc.initial);
8206 e.type = Type.tsize_t;
8207 v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
8208 v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
8211 *pvar = v;
8213 (*pvar).dsymbolSemantic(ass._scope);
8214 return setResult((*pvar));
8218 override void visit(Import imp)
8220 //printf("%s.Import.search(ident = '%s', flags = x%x)\n", imp.toChars(), ident.toChars(), flags);
8221 if (!imp.pkg)
8223 imp.load(null);
8224 imp.mod.importAll(null);
8225 imp.mod.dsymbolSemantic(null);
8227 // Forward it to the package/module
8228 return setResult(imp.pkg.search(loc, ident, flags));
8232 override void visit(Nspace ns)
8234 //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars());
8235 if (ns._scope && !ns.symtab)
8236 dsymbolSemantic(ns, ns._scope);
8238 if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called
8240 if (!(flags & IgnoreErrors))
8241 .error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars());
8242 return setResult(null);
8245 visit(cast(ScopeDsymbol)ns);
8248 override void visit(EnumDeclaration em)
8250 //printf("%s.EnumDeclaration::search('%s')\n", em.toChars(), ident.toChars());
8251 if (em._scope)
8253 // Try one last time to resolve this enum
8254 dsymbolSemantic(em, em._scope);
8257 visit(cast(ScopeDsymbol)em);
8260 override void visit(Package pkg)
8262 //printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags);
8263 flags &= ~SearchLocalsOnly; // searching an import is always transitive
8264 if (!pkg.isModule() && pkg.mod)
8266 // Prefer full package name.
8267 Dsymbol s = pkg.symtab ? pkg.symtab.lookup(ident) : null;
8268 if (s)
8269 return setResult(s);
8270 //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
8271 return setResult(pkg.mod.search(loc, ident, flags));
8274 visit(cast(ScopeDsymbol)pkg);
8277 override void visit(Module m)
8279 /* Since modules can be circularly referenced,
8280 * need to stop infinite recursive searches.
8281 * This is done with the cache.
8283 //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", m.toChars(), ident.toChars(), flags, m.insearch);
8284 if (m.insearch)
8285 return setResult(null);
8287 /* Qualified module searches always search their imports,
8288 * even if SearchLocalsOnly
8290 if (!(flags & SearchUnqualifiedModule))
8291 flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly);
8293 if (m.searchCacheIdent == ident && m.searchCacheFlags == flags)
8295 //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
8296 // toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
8297 return setResult(m.searchCacheSymbol);
8300 uint errors = global.errors;
8302 m.insearch = true;
8303 visit(cast(ScopeDsymbol)m);
8304 Dsymbol s = result;
8305 m.insearch = false;
8307 if (errors == global.errors)
8309 // https://issues.dlang.org/show_bug.cgi?id=10752
8310 // Can cache the result only when it does not cause
8311 // access error so the side-effect should be reproduced in later search.
8312 m.searchCacheIdent = ident;
8313 m.searchCacheSymbol = s;
8314 m.searchCacheFlags = flags;
8316 return setResult(s);
8319 override void visit(Declaration decl)
8321 Dsymbol s = null;
8322 if (decl.type)
8324 s = decl.type.toDsymbol(decl._scope);
8325 if (s)
8326 s = s.search(loc, ident, flags);
8328 return setResult(s);
8331 override void visit(StructDeclaration sd)
8333 //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", sd.toChars(), ident.toChars(), flags);
8334 if (sd._scope && !sd.symtab)
8335 dsymbolSemantic(sd, sd._scope);
8337 if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called
8339 // .stringof is always defined (but may be hidden by some other symbol)
8340 if(ident != Id.stringof && !(flags & IgnoreErrors) && sd.semanticRun < PASS.semanticdone)
8341 .error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars());
8342 return setResult(null);
8345 visit(cast(ScopeDsymbol)sd);
8348 override void visit(ClassDeclaration cd)
8350 //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", cd.toChars(), ident.toChars(), flags);
8351 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
8352 if (cd._scope && cd.baseok < Baseok.semanticdone)
8354 if (!cd.inuse)
8356 // must semantic on base class/interfaces
8357 cd.inuse = true;
8358 dsymbolSemantic(cd, null);
8359 cd.inuse = false;
8363 if (!cd.members || !cd.symtab) // opaque or addMember is not yet done
8365 // .stringof is always defined (but may be hidden by some other symbol)
8366 if (ident != Id.stringof && !(flags & IgnoreErrors) && cd.semanticRun < PASS.semanticdone)
8367 cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
8368 //*(char*)0=0;
8369 return setResult(null);
8372 visit(cast(ScopeDsymbol)cd);
8373 auto s = result;
8375 // don't search imports of base classes
8376 if (flags & SearchImportsOnly)
8377 return setResult(s);
8379 if (s)
8380 return setResult(s);
8382 // Search bases classes in depth-first, left to right order
8383 foreach (b; (*cd.baseclasses)[])
8385 if (!b.sym)
8386 continue;
8388 if (!b.sym.symtab)
8390 cd.classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
8391 continue;
8394 import dmd.access : symbolIsVisible;
8396 s = b.sym.search(loc, ident, flags);
8397 if (!s)
8398 continue;
8399 else if (s == cd) // happens if s is nested in this and derives from this
8400 s = null;
8401 else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s))
8402 s = null;
8403 else
8404 break;
8407 return setResult(s);