rs6000, update effective target for tests builtins-10*.c and vec_perm-runnable-i128.c
[official-gcc.git] / gcc / d / dmd / dsymbolsem.d
blobb13f98aee73be4003becdfbb5037fca92d2d7658
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-2024 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.clone;
25 import dmd.cond;
26 import dmd.dcast;
27 import dmd.dclass;
28 import dmd.declaration;
29 import dmd.denum;
30 import dmd.dimport;
31 import dmd.dinterpret;
32 import dmd.dmodule;
33 import dmd.dscope;
34 import dmd.dstruct;
35 import dmd.dsymbol;
36 import dmd.dtemplate;
37 import dmd.dversion;
38 import dmd.enumsem;
39 import dmd.errors;
40 import dmd.escape;
41 import dmd.expression;
42 import dmd.expressionsem;
43 import dmd.func;
44 import dmd.funcsem;
45 import dmd.globals;
46 import dmd.id;
47 import dmd.identifier;
48 import dmd.importc;
49 import dmd.init;
50 import dmd.initsem;
51 import dmd.intrange;
52 import dmd.hdrgen;
53 import dmd.location;
54 import dmd.mtype;
55 import dmd.mustuse;
56 import dmd.nspace;
57 import dmd.objc;
58 import dmd.opover;
59 import dmd.optimize;
60 import dmd.parse;
61 import dmd.root.array;
62 import dmd.root.filename;
63 import dmd.common.outbuffer;
64 import dmd.root.rmem;
65 import dmd.rootobject;
66 import dmd.semantic2;
67 import dmd.semantic3;
68 import dmd.sideeffect;
69 import dmd.staticassert;
70 import dmd.tokens;
71 import dmd.utils;
72 import dmd.statement;
73 import dmd.target;
74 import dmd.templateparamsem;
75 import dmd.templatesem;
76 import dmd.typesem;
77 import dmd.visitor;
79 version (IN_GCC) {}
80 else version (IN_LLVM) {}
81 else version = MARS;
83 enum LOG = false;
85 /*************************************
86 * Does semantic analysis on the public face of declarations.
88 void dsymbolSemantic(Dsymbol dsym, Scope* sc)
90 scope v = new DsymbolSemanticVisitor(sc);
91 dsym.accept(v);
94 /***************************************************
95 * Determine the numerical value of the AlignmentDeclaration
96 * Params:
97 * ad = AlignmentDeclaration
98 * sc = context
99 * Returns:
100 * ad with alignment value determined
102 AlignDeclaration getAlignment(AlignDeclaration ad, Scope* sc)
104 if (!ad.salign.isUnknown()) // UNKNOWN is 0
105 return ad;
107 if (!ad.exps)
109 ad.salign.setDefault();
110 return ad;
113 dinteger_t strictest = 0; // strictest alignment
114 bool errors;
115 foreach (ref exp; (*ad.exps)[])
117 sc = sc.startCTFE();
118 auto e = exp.expressionSemantic(sc);
119 e = resolveProperties(sc, e);
120 sc = sc.endCTFE();
121 e = e.ctfeInterpret();
122 exp = e; // could be re-evaluated if exps are assigned to more than one AlignDeclaration by CParser.applySpecifier(),
123 // e.g. `_Alignas(8) int a, b;`
124 if (e.op == EXP.error)
125 errors = true;
126 else
128 auto n = e.toInteger();
129 if (sc.flags & SCOPE.Cfile && n == 0) // C11 6.7.5-6 allows 0 for alignment
130 continue;
132 if (n < 1 || n & (n - 1) || ushort.max < n || !e.type.isintegral())
134 error(ad.loc, "alignment must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
135 errors = true;
137 if (n > strictest) // C11 6.7.5-6
138 strictest = n;
142 if (errors || strictest == 0) // C11 6.7.5-6 says alignment of 0 means no effect
143 ad.salign.setDefault();
144 else
145 ad.salign.set(cast(uint) strictest);
147 return ad;
150 const(char)* getMessage(DeprecatedDeclaration dd)
152 if (auto sc = dd._scope)
154 dd._scope = null;
156 sc = sc.startCTFE();
157 dd.msg = dd.msg.expressionSemantic(sc);
158 dd.msg = resolveProperties(sc, dd.msg);
159 sc = sc.endCTFE();
160 dd.msg = dd.msg.ctfeInterpret();
162 if (auto se = dd.msg.toStringExp())
163 dd.msgstr = se.toStringz().ptr;
164 else
165 error(dd.msg.loc, "compile time constant expected, not `%s`", dd.msg.toChars());
167 return dd.msgstr;
170 bool checkDeprecated(Dsymbol d, const ref Loc loc, Scope* sc)
172 if (global.params.useDeprecated == DiagnosticReporting.off)
173 return false;
174 if (!d.isDeprecated())
175 return false;
176 // Don't complain if we're inside a deprecated symbol's scope
177 if (sc.isDeprecated())
178 return false;
179 // Don't complain if we're inside a template constraint
180 // https://issues.dlang.org/show_bug.cgi?id=21831
181 if (sc.flags & SCOPE.constraint)
182 return false;
184 const(char)* message = null;
185 for (Dsymbol p = d; p; p = p.parent)
187 message = p.depdecl ? p.depdecl.getMessage() : null;
188 if (message)
189 break;
191 if (message)
192 deprecation(loc, "%s `%s` is deprecated - %s", d.kind, d.toPrettyChars, message);
193 else
194 deprecation(loc, "%s `%s` is deprecated", d.kind, d.toPrettyChars);
196 if (auto ti = sc.parent ? sc.parent.isInstantiated() : null)
197 ti.printInstantiationTrace(Classification.deprecation);
198 else if (auto ti = sc.parent ? sc.parent.isTemplateInstance() : null)
199 ti.printInstantiationTrace(Classification.deprecation);
201 return true;
204 /*********************************
205 * Check type to see if it is based on a deprecated symbol.
207 private void checkDeprecated(Type type, const ref Loc loc, Scope* sc)
209 if (Dsymbol s = type.toDsymbol(sc))
211 s.checkDeprecated(loc, sc);
214 if (auto tn = type.nextOf())
215 tn.checkDeprecated(loc, sc);
218 // Returns true if a contract can appear without a function body.
219 package bool allowsContractWithoutBody(FuncDeclaration funcdecl)
221 assert(!funcdecl.fbody);
223 /* Contracts can only appear without a body when they are virtual
224 * interface functions or abstract.
226 Dsymbol parent = funcdecl.toParent();
227 InterfaceDeclaration id = parent.isInterfaceDeclaration();
229 if (!funcdecl.isAbstract() &&
230 (funcdecl.fensures || funcdecl.frequires) &&
231 !(id && funcdecl.isVirtual()))
233 auto cd = parent.isClassDeclaration();
234 if (!(cd && cd.isAbstract()))
235 return false;
237 return true;
241 Tests whether the `ctor` that is part of `ti` is an rvalue constructor
242 (i.e. a constructor that receives a single parameter of the same type as
243 `Unqual!typeof(this)`). If that is the case and `sd` contains a copy
244 constructor, than an error is issued.
246 Params:
247 sd = struct declaration that may contin both an rvalue and copy constructor
248 ctor = constructor that will be checked if it is an evalue constructor
249 ti = template instance the ctor is part of
251 Return:
252 `false` if ctor is not an rvalue constructor or if `sd` does not contain a
253 copy constructor. `true` otherwise
255 bool checkHasBothRvalueAndCpCtor(StructDeclaration sd, CtorDeclaration ctor, TemplateInstance ti)
257 auto loc = ctor.loc;
258 auto tf = cast(TypeFunction)ctor.type;
259 auto dim = tf.parameterList.length;
260 if (sd && sd.hasCopyCtor && (dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
262 auto param = tf.parameterList[0];
263 if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
265 .error(loc, "cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars());
266 .errorSupplemental(ti.loc, "Template instance `%s` creates an rvalue constructor for `struct %s`",
267 ti.toPrettyChars(), sd.toChars());
269 return true;
273 return false;
276 /*************************************
277 * Find the `alias this` symbol of e's type.
278 * Params:
279 * sc = context
280 * e = expression forming the `this`
281 * gag = do not print errors, return `null` instead
282 * findOnly = don't do further processing like resolving properties,
283 * i.e. just return plain dotExp() result.
284 * Returns:
285 * Expression that is `e.aliasthis`
287 Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool findOnly = false)
289 import dmd.typesem : dotExp;
290 for (AggregateDeclaration ad = isAggregate(e.type); ad;)
292 if (ad.aliasthis)
294 Loc loc = e.loc;
295 Type tthis = (e.op == EXP.type ? e.type : null);
296 const flags = cast(DotExpFlag) (DotExpFlag.noAliasThis | (gag * DotExpFlag.gag));
297 uint olderrors = gag ? global.startGagging() : 0;
298 e = dotExp(ad.type, sc, e, ad.aliasthis.ident, flags);
299 if (!e || findOnly)
300 return gag && global.endGagging(olderrors) ? null : e;
302 if (tthis && ad.aliasthis.sym.needThis())
304 if (auto ve = e.isVarExp())
306 if (auto fd = ve.var.isFuncDeclaration())
308 // https://issues.dlang.org/show_bug.cgi?id=13009
309 // Support better match for the overloaded alias this.
310 bool hasOverloads;
311 if (auto f = fd.overloadModMatch(loc, tthis, hasOverloads))
313 if (!hasOverloads)
314 fd = f; // use exact match
315 e = new VarExp(loc, fd, hasOverloads);
316 e.type = f.type;
317 e = new CallExp(loc, e);
318 goto L1;
322 /* non-@property function is not called inside typeof(),
323 * so resolve it ahead.
326 int save = sc.intypeof;
327 sc.intypeof = 1; // bypass "need this" error check
328 e = resolveProperties(sc, e);
329 sc.intypeof = save;
332 e = new TypeExp(loc, new TypeTypeof(loc, e));
333 e = e.expressionSemantic(sc);
335 e = resolveProperties(sc, e);
336 if (!gag)
337 ad.aliasthis.checkDeprecatedAliasThis(loc, sc);
338 else if (global.endGagging(olderrors))
339 e = null;
342 import dmd.dclass : ClassDeclaration;
343 auto cd = ad.isClassDeclaration();
344 if ((!e || !ad.aliasthis) && cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
346 ad = cd.baseClass;
347 continue;
349 break;
351 return e;
355 * Check if an `alias this` is deprecated
357 * Usually one would use `expression.checkDeprecated(scope, aliasthis)` to
358 * check if `expression` uses a deprecated `aliasthis`, but this calls
359 * `toPrettyChars` which lead to the following message:
360 * "Deprecation: alias this `fullyqualified.aggregate.__anonymous` is deprecated"
362 * Params:
363 * at = The `AliasThis` object to check
364 * loc = `Loc` of the expression triggering the access to `at`
365 * sc = `Scope` of the expression
366 * (deprecations do not trigger in deprecated scopes)
368 * Returns:
369 * Whether the alias this was reported as deprecated.
371 private bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc)
373 if (global.params.useDeprecated != DiagnosticReporting.off
374 && at.isDeprecated() && !sc.isDeprecated())
376 const(char)* message = null;
377 for (Dsymbol p = at; p; p = p.parent)
379 message = p.depdecl ? p.depdecl.getMessage() : null;
380 if (message)
381 break;
383 if (message)
384 deprecation(loc, "`alias %s this` is deprecated - %s",
385 at.sym.toChars(), message);
386 else
387 deprecation(loc, "`alias %s this` is deprecated",
388 at.sym.toChars());
390 if (auto ti = sc.parent ? sc.parent.isInstantiated() : null)
391 ti.printInstantiationTrace(Classification.deprecation);
393 return true;
395 return false;
398 // Save the scope and defer semantic analysis on the Dsymbol.
399 void deferDsymbolSemantic(Scope* sc, Dsymbol s, Scope *scx)
401 s._scope = scx ? scx : sc.copy();
402 s._scope.setNoFree();
403 Module.addDeferredSemantic(s);
407 private extern(C++) final class DsymbolSemanticVisitor : Visitor
409 alias visit = Visitor.visit;
411 Scope* sc;
412 this(Scope* sc) scope @safe
414 this.sc = sc;
417 override void visit(Dsymbol dsym)
419 .error(dsym.loc, "%s `%s` %p has no semantic routine", dsym.kind, dsym.toPrettyChars, dsym);
422 override void visit(ScopeDsymbol) { }
423 override void visit(Declaration) { }
425 override void visit(AliasThis dsym)
427 if (dsym.semanticRun != PASS.initial)
428 return;
430 if (dsym._scope)
432 sc = dsym._scope;
433 dsym._scope = null;
436 if (!sc)
437 return;
439 dsym.semanticRun = PASS.semantic;
440 dsym.isDeprecated_ = !!(sc.stc & STC.deprecated_);
442 Dsymbol p = sc.parent.pastMixin();
443 AggregateDeclaration ad = p.isAggregateDeclaration();
444 if (!ad)
446 error(dsym.loc, "alias this can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
447 return;
450 assert(ad.members);
451 Dsymbol s = ad.search(dsym.loc, dsym.ident);
452 if (!s)
454 Dsymbol pscopesym;
455 s = sc.search(dsym.loc, dsym.ident, pscopesym);
456 if (s)
457 error(dsym.loc, "`%s` is not a member of `%s`", s.toChars(), ad.toChars());
458 else
459 error(dsym.loc, "undefined identifier `%s`", dsym.ident.toChars());
460 return;
462 if (ad.aliasthis && s != ad.aliasthis)
464 error(dsym.loc, "there can be only one alias this");
465 return;
468 /* disable the alias this conversion so the implicit conversion check
469 * doesn't use it.
471 ad.aliasthis = null;
473 Dsymbol sx = s;
474 if (sx.isAliasDeclaration())
475 sx = sx.toAlias();
476 Declaration d = sx.isDeclaration();
477 if (d && !d.isTupleDeclaration())
479 /* https://issues.dlang.org/show_bug.cgi?id=18429
481 * If the identifier in the AliasThis declaration
482 * is defined later and is a voldemort type, we must
483 * perform semantic on the declaration to deduce the type.
485 if (!d.type)
486 d.dsymbolSemantic(sc);
488 Type t = d.type;
489 assert(t);
490 if (ad.type.implicitConvTo(t) > MATCH.nomatch)
492 error(dsym.loc, "alias this is not reachable as `%s` already converts to `%s`", ad.toChars(), t.toChars());
496 dsym.sym = s;
497 // Restore alias this
498 ad.aliasthis = dsym;
499 dsym.semanticRun = PASS.semanticdone;
502 override void visit(AliasDeclaration dsym)
504 if (dsym.semanticRun >= PASS.semanticdone)
505 return;
506 assert(dsym.semanticRun <= PASS.semantic);
508 if (!sc)
509 return;
511 dsym.semanticRun = PASS.semantic;
513 dsym.storage_class |= sc.stc & STC.deprecated_;
514 dsym.visibility = sc.visibility;
515 dsym.userAttribDecl = sc.userAttribDecl;
517 if (!sc.func && dsym.inNonRoot())
518 return;
520 aliasSemantic(dsym, sc);
523 override void visit(AliasAssign dsym)
525 //printf("visit(AliasAssign)\n");
526 if (dsym.semanticRun >= PASS.semanticdone)
527 return;
528 assert(dsym.semanticRun <= PASS.semantic);
530 if (!sc.func && dsym.inNonRoot())
531 return;
533 aliasAssignSemantic(dsym, sc);
536 override void visit(VarDeclaration dsym)
538 version (none)
540 printf("VarDeclaration::semantic('%s', parent = '%s') sem = %d\n",
541 dsym.toChars(), sc.parent ? sc.parent.toChars() : null, dsym.semanticRun);
542 printf(" type = %s\n", dsym.type ? dsym.type.toChars() : "null");
543 printf(" stc = x%llx\n", dsym.storage_class);
544 printf(" storage_class = x%llx\n", dsym.storage_class);
545 printf("linkage = %d\n", dsym._linkage);
546 //if (strcmp(toChars(), "mul") == 0) assert(0);
548 //if (semanticRun > PASS.initial)
549 // return;
550 //semanticRun = PSSsemantic;
552 if (dsym.semanticRun >= PASS.semanticdone)
553 return;
555 if (sc && sc.inunion && sc.inunion.isAnonDeclaration())
556 dsym.overlapped = true;
558 dsym.sequenceNumber = global.varSequenceNumber++;
559 if (!dsym.isScope())
560 dsym.maybeScope = true;
562 Scope* scx = null;
563 if (dsym._scope)
565 sc = dsym._scope;
566 scx = sc;
567 dsym._scope = null;
570 if (!sc)
571 return;
573 dsym.semanticRun = PASS.semantic;
575 // 'static foreach' variables should not inherit scope properties
576 // https://issues.dlang.org/show_bug.cgi?id=19482
577 if ((dsym.storage_class & (STC.foreach_ | STC.local)) == (STC.foreach_ | STC.local))
579 dsym._linkage = LINK.d;
580 dsym.visibility = Visibility(Visibility.Kind.public_);
581 dsym.overlapped = false; // unset because it is modified early on this function
582 dsym.userAttribDecl = null; // unset because it is set by Dsymbol.setScope()
584 else
586 /* Pick up storage classes from context, but except synchronized,
587 * override, abstract, and final.
589 dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
590 dsym.userAttribDecl = sc.userAttribDecl;
591 dsym.cppnamespace = sc.namespace;
592 dsym._linkage = sc.linkage;
593 dsym.visibility = sc.visibility;
594 dsym.alignment = sc.alignment();
597 if (dsym.storage_class & STC.extern_ && dsym._init)
598 .error(dsym.loc, "%s `%s` extern symbols cannot have initializers", dsym.kind, dsym.toPrettyChars);
600 AggregateDeclaration ad = dsym.isThis();
601 if (ad)
602 dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
604 /* If auto type inference, do the inference
606 int inferred = 0;
607 if (!dsym.type)
609 dsym.inuse++;
611 // Infering the type requires running semantic,
612 // so mark the scope as ctfe if required
613 bool needctfe = (dsym.storage_class & (STC.manifest | STC.static_)) != 0 || !sc.func;
614 if (needctfe)
616 sc.flags |= SCOPE.condition;
617 sc = sc.startCTFE();
619 //printf("inferring type for %s with init %s\n", dsym.toChars(), dsym._init.toChars());
620 dsym._init = dsym._init.inferType(sc);
621 dsym.type = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0).type;
622 if (needctfe)
623 sc = sc.endCTFE();
625 dsym.inuse--;
626 inferred = 1;
628 /* This is a kludge to support the existing syntax for RAII
629 * declarations.
631 dsym.storage_class &= ~STC.auto_;
632 dsym.originalType = dsym.type.syntaxCopy();
634 else
636 if (!dsym.originalType)
637 dsym.originalType = dsym.type.syntaxCopy();
639 /* Prefix function attributes of variable declaration can affect
640 * its type:
641 * pure nothrow void function() fp;
642 * static assert(is(typeof(fp) == void function() pure nothrow));
644 Scope* sc2 = sc.push();
645 sc2.stc |= (dsym.storage_class & STC.FUNCATTR);
646 dsym.inuse++;
647 dsym.type = dsym.type.typeSemantic(dsym.loc, sc2);
648 dsym.inuse--;
649 sc2.pop();
651 //printf(" semantic type = %s\n", dsym.type ? dsym.type.toChars() : "null");
652 if (dsym.type.ty == Terror)
653 dsym.errors = true;
655 dsym.type.checkDeprecated(dsym.loc, sc);
656 dsym.parent = sc.parent;
657 //printf("this = %p, parent = %p, '%s'\n", dsym, dsym.parent, dsym.parent.toChars());
659 /* If scope's alignment is the default, use the type's alignment,
660 * otherwise the scope overrrides.
662 if (dsym.alignment.isDefault())
663 dsym.alignment = dsym.type.alignment(); // use type's alignment
665 //printf("sc.stc = %x\n", sc.stc);
666 //printf("storage_class = x%x\n", storage_class);
668 dsym.type.checkComplexTransition(dsym.loc, sc);
670 // Calculate type size + safety checks
671 if (dsym.storage_class & STC.gshared && !dsym.isMember())
673 sc.setUnsafe(false, dsym.loc, "__gshared not allowed in safe functions; use shared");
676 Dsymbol parent = dsym.toParent();
678 Type tb = dsym.type.toBasetype();
679 Type tbn = tb.baseElemOf();
680 if (tb.ty == Tvoid && !(dsym.storage_class & STC.lazy_))
682 if (inferred)
684 .error(dsym.loc, "%s `%s` - type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`",
685 dsym.kind, dsym.toPrettyChars, dsym.type.toChars(), toChars(dsym._init));
687 else
688 .error(dsym.loc, "%s `%s` - variables cannot be of type `void`", dsym.kind, dsym.toPrettyChars);
689 dsym.type = Type.terror;
690 tb = dsym.type;
692 if (tb.ty == Tfunction)
694 .error(dsym.loc, "%s `%s` cannot be declared to be a function", dsym.kind, dsym.toPrettyChars);
695 dsym.type = Type.terror;
696 tb = dsym.type;
698 if (auto ts = tb.isTypeStruct())
700 // Require declarations, except when it's just a reference (as done for pointers)
701 // or when the variable is defined externally
702 if (!ts.sym.members && !(dsym.storage_class & (STC.ref_ | STC.extern_)))
704 .error(dsym.loc, "%s `%s` - no definition of struct `%s`", dsym.kind, dsym.toPrettyChars, ts.toChars());
706 // Explain why the definition is required when it's part of another type
707 if (!dsym.type.isTypeStruct())
709 // Prefer Loc of the dependant type
710 const s = dsym.type.toDsymbol(sc);
711 const loc = (s ? s : dsym).loc;
712 loc.errorSupplemental("required by type `%s`", dsym.type.toChars());
714 errorSupplemental(dsym.loc, "see https://dlang.org/spec/struct.html#opaque_struct_unions");
715 errorSupplemental(dsym.loc, "perhaps declare a variable with pointer type `%s*` instead", dsym.type.toChars());
717 // Flag variable as error to avoid invalid error messages due to unknown size
718 dsym.type = Type.terror;
721 if ((dsym.storage_class & STC.auto_) && !inferred)
722 .error(dsym.loc, "%s `%s` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?", dsym.kind, dsym.toPrettyChars);
724 if (auto tt = tb.isTypeTuple())
726 /* Instead, declare variables for each of the tuple elements
727 * and add those.
729 size_t nelems = Parameter.dim(tt.arguments);
730 Expression ie = (dsym._init && !dsym._init.isVoidInitializer()) ? dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0) : null;
731 if (ie)
732 ie = ie.expressionSemantic(sc);
733 if (nelems > 0 && ie)
735 auto iexps = new Expressions();
736 iexps.push(ie);
737 auto exps = new Expressions();
738 for (size_t pos = 0; pos < iexps.length; pos++)
740 Lexpand1:
741 Expression e = (*iexps)[pos];
742 Parameter arg = Parameter.getNth(tt.arguments, pos);
743 arg.type = arg.type.typeSemantic(dsym.loc, sc);
744 //printf("[%d] iexps.length = %d, ", pos, iexps.length);
745 //printf("e = (%s %s, %s), ", Token.tochars[e.op], e.toChars(), e.type.toChars());
746 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
748 if (e != ie)
750 if (iexps.length > nelems)
751 goto Lnomatch;
752 if (e.type.implicitConvTo(arg.type))
753 continue;
756 if (auto te = e.isTupleExp())
758 if (iexps.length - 1 + te.exps.length > nelems)
759 goto Lnomatch;
761 iexps.remove(pos);
762 iexps.insert(pos, te.exps);
763 (*iexps)[pos] = Expression.combine(te.e0, (*iexps)[pos]);
764 goto Lexpand1;
766 else if (isAliasThisTuple(e))
768 auto v = copyToTemp(0, "__tup", e);
769 v.dsymbolSemantic(sc);
770 auto ve = new VarExp(dsym.loc, v);
771 ve.type = e.type;
773 exps.setDim(1);
774 (*exps)[0] = ve;
775 expandAliasThisTuples(exps, 0);
777 for (size_t u = 0; u < exps.length; u++)
779 Lexpand2:
780 Expression ee = (*exps)[u];
781 arg = Parameter.getNth(tt.arguments, pos + u);
782 arg.type = arg.type.typeSemantic(dsym.loc, sc);
783 //printf("[%d+%d] exps.length = %d, ", pos, u, exps.length);
784 //printf("ee = (%s %s, %s), ", Token.tochars[ee.op], ee.toChars(), ee.type.toChars());
785 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
787 size_t iexps_dim = iexps.length - 1 + exps.length;
788 if (iexps_dim > nelems)
789 goto Lnomatch;
790 if (ee.type.implicitConvTo(arg.type))
791 continue;
793 if (expandAliasThisTuples(exps, u) != -1)
794 goto Lexpand2;
797 if ((*exps)[0] != ve)
799 Expression e0 = (*exps)[0];
800 (*exps)[0] = new CommaExp(dsym.loc, new DeclarationExp(dsym.loc, v), e0);
801 (*exps)[0].type = e0.type;
803 iexps.remove(pos);
804 iexps.insert(pos, exps);
805 goto Lexpand1;
809 if (iexps.length < nelems)
810 goto Lnomatch;
812 ie = new TupleExp(dsym._init.loc, iexps);
814 Lnomatch:
816 if (ie && ie.op == EXP.tuple)
818 auto te = ie.isTupleExp();
819 size_t tedim = te.exps.length;
820 if (tedim != nelems)
822 error(dsym.loc, "sequence of %d elements cannot be assigned to sequence of %d elements", cast(int)tedim, cast(int)nelems);
823 for (size_t u = tedim; u < nelems; u++) // fill dummy expression
824 te.exps.push(ErrorExp.get());
828 auto exps = new Objects(nelems);
829 for (size_t i = 0; i < nelems; i++)
831 Parameter arg = Parameter.getNth(tt.arguments, i);
833 OutBuffer buf;
834 buf.printf("__%s_field_%llu", dsym.ident.toChars(), cast(ulong)i);
835 auto id = Identifier.idPool(buf[]);
837 Initializer ti;
838 if (ie)
840 Expression einit = ie;
841 if (auto te = ie.isTupleExp())
843 einit = (*te.exps)[i];
844 if (i == 0)
845 einit = Expression.combine(te.e0, einit);
847 ti = new ExpInitializer(einit.loc, einit);
849 else
850 ti = dsym._init ? dsym._init.syntaxCopy() : null;
852 StorageClass storage_class = STC.temp | dsym.storage_class;
853 if ((dsym.storage_class & STC.parameter) && (arg.storageClass & STC.parameter))
854 storage_class |= arg.storageClass;
855 auto v = new VarDeclaration(dsym.loc, arg.type, id, ti, storage_class);
856 //printf("declaring field %s of type %s\n", v.toChars(), v.type.toChars());
857 v.overlapped = dsym.overlapped;
859 v.dsymbolSemantic(sc);
861 Expression e = new VarExp(dsym.loc, v);
862 (*exps)[i] = e;
864 auto v2 = new TupleDeclaration(dsym.loc, dsym.ident, exps);
865 v2.parent = dsym.parent;
866 v2.isexp = true;
867 dsym.aliasTuple = v2;
868 dsym.semanticRun = PASS.semanticdone;
869 return;
872 /* Storage class can modify the type
874 dsym.type = dsym.type.addStorageClass(dsym.storage_class);
876 /* Adjust storage class to reflect type
878 if (dsym.type.isConst())
880 dsym.storage_class |= STC.const_;
881 if (dsym.type.isShared())
882 dsym.storage_class |= STC.shared_;
884 else if (dsym.type.isImmutable())
885 dsym.storage_class |= STC.immutable_;
886 else if (dsym.type.isShared())
887 dsym.storage_class |= STC.shared_;
888 else if (dsym.type.isWild())
889 dsym.storage_class |= STC.wild;
891 if (StorageClass stc = dsym.storage_class & (STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_))
893 if (stc == STC.final_)
894 .error(dsym.loc, "%s `%s` cannot be `final`, perhaps you meant `const`?", dsym.kind, dsym.toPrettyChars);
895 else
897 OutBuffer buf;
898 stcToBuffer(buf, stc);
899 .error(dsym.loc, "%s `%s` cannot be `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
901 dsym.storage_class &= ~stc; // strip off
904 // At this point we can add `scope` to the STC instead of `in`,
905 // because we are never going to use this variable's STC for user messages
906 if (dsym.storage_class & STC.constscoperef)
907 dsym.storage_class |= STC.scope_;
909 if (dsym.storage_class & STC.scope_)
911 StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
912 if (stc)
914 OutBuffer buf;
915 stcToBuffer(buf, stc);
916 .error(dsym.loc, "%s `%s` cannot be `scope` and `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
918 else if (dsym.isMember())
920 error(dsym.loc, "field `%s` cannot be `scope`", dsym.toChars());
922 else if (!dsym.type.hasPointers())
924 dsym.storage_class &= ~STC.scope_; // silently ignore; may occur in generic code
925 // https://issues.dlang.org/show_bug.cgi?id=23168
926 if (dsym.storage_class & STC.returnScope)
928 dsym.storage_class &= ~(STC.return_ | STC.returnScope);
933 if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe))
936 else
938 AggregateDeclaration aad = parent.isAggregateDeclaration();
939 if (aad)
941 if (global.params.v.field && dsym.storage_class & (STC.const_ | STC.immutable_) && dsym._init && !dsym._init.isVoidInitializer())
943 const(char)* s = (dsym.storage_class & STC.immutable_) ? "immutable" : "const";
944 message(dsym.loc, "`%s.%s` is `%s` field", ad.toPrettyChars(), dsym.toChars(), s);
946 dsym.storage_class |= STC.field;
947 if (auto ts = tbn.isTypeStruct())
948 if (ts.sym.noDefaultCtor)
950 if (!dsym.isThisDeclaration() && !dsym._init)
951 aad.noDefaultCtor = true;
955 InterfaceDeclaration id = parent.isInterfaceDeclaration();
956 if (id)
958 error(dsym.loc, "field `%s` not allowed in interface", dsym.toChars());
960 else if (aad && aad.sizeok == Sizeok.done)
962 error(dsym.loc, "cannot declare field `%s` because it will change the determined size of `%s`", dsym.toChars(), aad.toChars());
965 /* Templates cannot add fields to aggregates
967 TemplateInstance ti = parent.isTemplateInstance();
968 if (ti)
970 // Take care of nested templates
971 while (1)
973 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
974 if (!ti2)
975 break;
976 ti = ti2;
978 // If it's a member template
979 AggregateDeclaration ad2 = ti.tempdecl.isMember();
980 if (ad2 && dsym.storage_class != STC.undefined_)
982 .error(dsym.loc, "%s `%s` - cannot use template to add field to aggregate `%s`", dsym.kind, dsym.toPrettyChars, ad2.toChars());
987 /* If the alignment of a stack local is greater than the stack alignment,
988 * note it in the enclosing function's alignSectionVars
990 version (MARS)
992 if (!dsym.alignment.isDefault() && sc.func &&
993 dsym.alignment.get() > target.stackAlign() &&
994 sc.func && !dsym.isDataseg() && !dsym.isParameter() && !dsym.isField())
996 auto fd = sc.func;
997 if (!fd.alignSectionVars)
998 fd.alignSectionVars = new VarDeclarations();
999 fd.alignSectionVars.push(dsym);
1003 if ((dsym.storage_class & (STC.ref_ | STC.parameter | STC.foreach_ | STC.temp | STC.result)) == STC.ref_ && dsym.ident != Id.This)
1005 .error(dsym.loc, "%s `%s` - only parameters, functions and `foreach` declarations can be `ref`", dsym.kind, dsym.toPrettyChars);
1008 if (dsym.type.hasWild())
1010 if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
1012 .error(dsym.loc, "%s `%s` - only parameters or stack-based variables can be `inout`", dsym.kind, dsym.toPrettyChars);
1014 FuncDeclaration func = sc.func;
1015 if (func)
1017 if (func.fes)
1018 func = func.fes.func;
1019 bool isWild = false;
1020 for (FuncDeclaration fd = func; fd; fd = fd.toParentDecl().isFuncDeclaration())
1022 if (fd.type.isTypeFunction().iswild)
1024 isWild = true;
1025 break;
1028 if (!isWild)
1030 .error(dsym.loc, "%s `%s` - `inout` variables can only be declared inside `inout` functions", dsym.kind, dsym.toPrettyChars);
1035 if (!(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.ref_ | STC.result)) &&
1036 tbn.ty == Tstruct && tbn.isTypeStruct().sym.noDefaultCtor)
1038 if (!dsym._init)
1040 if (dsym.isField())
1042 /* For fields, we'll check the constructor later to make sure it is initialized
1044 dsym.storage_class |= STC.nodefaultctor;
1046 else if (dsym.storage_class & STC.parameter)
1049 else
1050 .error(dsym.loc, "%s `%s` - default construction is disabled for type `%s`", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1054 FuncDeclaration fd = parent.isFuncDeclaration();
1055 if (dsym.type.isscope() && !(dsym.storage_class & STC.nodtor))
1057 if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.gshared) || !fd)
1059 .error(dsym.loc, "%s `%s` globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`", dsym.kind, dsym.toPrettyChars);
1062 // @@@DEPRECATED_2.097@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
1063 // Deprecated in 2.087
1064 // Remove this when the feature is removed from the language
1065 if (!(dsym.storage_class & STC.scope_))
1067 if (!(dsym.storage_class & STC.parameter) && dsym.ident != Id.withSym)
1068 .error(dsym.loc, "%s `%s` reference to `scope class` must be `scope`", dsym.kind, dsym.toPrettyChars);
1072 // Calculate type size + safety checks
1073 if (sc && sc.func)
1075 if (dsym._init && dsym._init.isVoidInitializer())
1078 if (dsym.type.hasPointers()) // also computes type size
1079 sc.setUnsafe(false, dsym.loc,
1080 "`void` initializers for pointers not allowed in safe functions");
1081 else if (dsym.type.hasInvariant())
1082 sc.setUnsafe(false, dsym.loc,
1083 "`void` initializers for structs with invariants are not allowed in safe functions");
1084 else if (dsym.type.hasSystemFields())
1085 sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc,
1086 "`void` initializers for `@system` variables not allowed in safe functions");
1088 else if (!dsym._init &&
1089 !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
1090 dsym.type.hasVoidInitPointers())
1092 sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions");
1096 if ((!dsym._init || dsym._init.isVoidInitializer) && !fd)
1098 // If not mutable, initializable by constructor only
1099 dsym.setInCtorOnly = true;
1102 if (dsym._init)
1103 { } // remember we had an explicit initializer
1104 else if (dsym.storage_class & STC.manifest)
1105 .error(dsym.loc, "%s `%s` - manifest constants must have initializers", dsym.kind, dsym.toPrettyChars);
1107 // Don't allow non-extern, non-__gshared variables to be interfaced with C++
1108 if (dsym._linkage == LINK.cpp && !(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.gshared)) && dsym.isDataseg())
1110 const char* p = (dsym.storage_class & STC.shared_) ? "shared" : "static";
1111 .error(dsym.loc, "%s `%s` cannot have `extern(C++)` linkage because it is `%s`", dsym.kind, dsym.toPrettyChars, p);
1112 errorSupplemental(dsym.loc, "perhaps declare it as `__gshared` instead");
1113 dsym.errors = true;
1116 bool isBlit = false;
1117 uinteger_t sz;
1118 if (sc.flags & SCOPE.Cfile && !dsym._init)
1120 addDefaultCInitializer(dsym);
1122 if (!dsym._init &&
1123 !(dsym.storage_class & (STC.static_ | STC.gshared | STC.extern_)) &&
1124 fd &&
1125 (!(dsym.storage_class & (STC.field | STC.in_ | STC.foreach_ | STC.parameter | STC.result)) ||
1126 (dsym.storage_class & STC.out_)) &&
1127 (sz = dsym.type.size()) != 0)
1129 // Provide a default initializer
1131 //printf("Providing default initializer for '%s'\n", dsym.toChars());
1132 if (sz == SIZE_INVALID && dsym.type.ty != Terror)
1133 .error(dsym.loc, "%s `%s` - size of type `%s` is invalid", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1135 Type tv = dsym.type;
1136 while (tv.ty == Tsarray) // Don't skip Tenum
1137 tv = tv.nextOf();
1138 if (tv.needsNested())
1140 /* Nested struct requires valid enclosing frame pointer.
1141 * In StructLiteralExp::toElem(), it's calculated.
1143 assert(tbn.ty == Tstruct);
1144 checkFrameAccess(dsym.loc, sc, tbn.isTypeStruct().sym);
1146 Expression e = tv.defaultInitLiteral(dsym.loc);
1147 e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1148 e = e.expressionSemantic(sc);
1149 dsym._init = new ExpInitializer(dsym.loc, e);
1150 goto Ldtor;
1152 if (tv.ty == Tstruct && tv.isTypeStruct().sym.zeroInit)
1154 /* If a struct is all zeros, as a special case
1155 * set its initializer to the integer 0.
1156 * In AssignExp::toElem(), we check for this and issue
1157 * a memset() to initialize the struct.
1158 * Must do same check in interpreter.
1160 Expression e = IntegerExp.literal!0;
1161 e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1162 e.type = dsym.type; // don't type check this, it would fail
1163 dsym._init = new ExpInitializer(dsym.loc, e);
1164 goto Ldtor;
1166 if (dsym.type.baseElemOf().ty == Tvoid)
1168 .error(dsym.loc, "%s `%s` of type `%s` does not have a default initializer", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1170 else if (auto e = dsym.type.defaultInit(dsym.loc))
1172 dsym._init = new ExpInitializer(dsym.loc, e);
1175 // Default initializer is always a blit
1176 isBlit = true;
1178 if (dsym._init)
1180 sc = sc.push();
1181 sc.stc &= ~(STC.TYPECTOR | STC.pure_ | STC.nothrow_ | STC.nogc | STC.ref_ | STC.disable);
1183 if (sc.flags & SCOPE.Cfile &&
1184 dsym.type.isTypeSArray() &&
1185 dsym.type.isTypeSArray().isIncomplete() &&
1186 dsym._init.isVoidInitializer() &&
1187 !(dsym.storage_class & STC.field))
1189 .error(dsym.loc, "%s `%s` - incomplete array type must have initializer", dsym.kind, dsym.toPrettyChars);
1192 ExpInitializer ei = dsym._init.isExpInitializer();
1194 if (ei) // https://issues.dlang.org/show_bug.cgi?id=13424
1195 // Preset the required type to fail in FuncLiteralDeclaration::semantic3
1196 ei.exp = inferType(ei.exp, dsym.type);
1198 // If inside function, there is no semantic3() call
1199 if (sc.func || sc.intypeof == 1)
1201 // If local variable, use AssignExp to handle all the various
1202 // possibilities.
1203 if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
1205 //printf("fd = '%s', var = '%s'\n", fd.toChars(), dsym.toChars());
1206 if (!ei)
1208 ArrayInitializer ai = dsym._init.isArrayInitializer();
1209 Expression e;
1210 if (ai && tb.ty == Taarray)
1211 e = ai.toAssocArrayLiteral();
1212 else
1213 e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
1214 if (!e)
1216 // Run semantic, but don't need to interpret
1217 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITnointerpret);
1218 e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
1219 if (!e)
1221 .error(dsym.loc, "%s `%s` is not a static and cannot have static initializer", dsym.kind, dsym.toPrettyChars);
1222 e = ErrorExp.get();
1225 ei = new ExpInitializer(dsym._init.loc, e);
1226 dsym._init = ei;
1228 else if (sc.flags & SCOPE.Cfile && dsym.type.isTypeSArray() &&
1229 dsym.type.isTypeSArray().isIncomplete())
1231 // C11 6.7.9-22 determine the size of the incomplete array,
1232 // or issue an error that the initializer is invalid.
1233 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
1236 if (ei && dsym.isScope())
1238 Expression ex = ei.exp.lastComma();
1239 if (ex.op == EXP.blit || ex.op == EXP.construct)
1240 ex = (cast(AssignExp)ex).e2;
1241 if (auto ne = ex.isNewExp())
1243 /* See if initializer is a NewExp that can be allocated on the stack.
1245 if (dsym.type.toBasetype().ty == Tclass)
1247 /* Unsafe to allocate on stack if constructor is not `scope` because the `this` can leak.
1248 * https://issues.dlang.org/show_bug.cgi?id=23145
1250 if (ne.member && !(ne.member.storage_class & STC.scope_))
1252 import dmd.escape : setUnsafeDIP1000;
1253 const inSafeFunc = sc.func && sc.func.isSafeBypassingInference(); // isSafeBypassingInference may call setUnsafe().
1254 if (sc.setUnsafeDIP1000(false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym))
1255 errorSupplemental(ne.member.loc, "is the location of the constructor");
1257 ne.onstack = 1;
1258 dsym.onstack = true;
1261 else if (auto fe = ex.isFuncExp())
1263 // or a delegate that doesn't escape a reference to the function
1264 FuncDeclaration f = fe.fd;
1265 if (f.tookAddressOf)
1266 f.tookAddressOf--;
1268 else if (auto ale = ex.isArrayLiteralExp())
1270 // or an array literal assigned to a `scope` variable
1271 if (sc.useDIP1000 == FeatureState.enabled
1272 && !dsym.type.nextOf().needsDestruction())
1273 ale.onstack = true;
1277 Expression exp = ei.exp;
1278 Expression e1 = new VarExp(dsym.loc, dsym);
1279 if (isBlit)
1280 exp = new BlitExp(dsym.loc, e1, exp);
1281 else
1282 exp = new ConstructExp(dsym.loc, e1, exp);
1283 dsym.canassign++;
1284 exp = exp.expressionSemantic(sc);
1285 dsym.canassign--;
1286 exp = exp.optimize(WANTvalue);
1287 if (exp.op == EXP.error)
1289 dsym._init = new ErrorInitializer();
1290 ei = null;
1292 else
1293 ei.exp = exp;
1295 else
1297 // https://issues.dlang.org/show_bug.cgi?id=14166
1298 // Don't run CTFE for the temporary variables inside typeof
1299 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret);
1300 import dmd.semantic2 : lowerStaticAAs;
1301 lowerStaticAAs(dsym, sc);
1302 auto init_err = dsym._init.isExpInitializer();
1303 if (init_err && init_err.exp.op == EXP.showCtfeContext)
1305 init_err.exp = ErrorExp.get();
1306 errorSupplemental(dsym.loc, "compile time context created here");
1310 else if (parent.isAggregateDeclaration())
1312 dsym._scope = scx ? scx : sc.copy();
1313 dsym._scope.setNoFree();
1315 else if (dsym.storage_class & (STC.const_ | STC.immutable_ | STC.manifest) ||
1316 dsym.type.isConst() || dsym.type.isImmutable() ||
1317 sc.flags & SCOPE.Cfile)
1319 /* Because we may need the results of a const declaration in a
1320 * subsequent type, such as an array dimension, before semantic2()
1321 * gets ordinarily run, try to run semantic2() now.
1322 * If a C array is of unknown size, the initializer can provide the size. Do this
1323 * eagerly because C does it eagerly.
1324 * Ignore failure.
1326 if (!inferred)
1328 uint errors = global.errors;
1329 dsym.inuse++;
1330 // Bug 20549. Don't try this on modules or packages, syntaxCopy
1331 // could crash (inf. recursion) on a mod/pkg referencing itself
1332 if (ei && (ei.exp.op != EXP.scope_ ? true : !ei.exp.isScopeExp().sds.isPackage()))
1334 if (ei.exp.type)
1336 // If exp is already resolved we are done, our original init exp
1337 // could have a type painting that we need to respect
1338 // e.g. ['a'] typed as string, or [['z'], ""] as string[]
1339 // See https://issues.dlang.org/show_bug.cgi?id=15711
1341 else
1343 Expression exp = ei.exp.syntaxCopy();
1345 bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
1346 if (needctfe)
1347 sc = sc.startCTFE();
1348 sc = sc.push();
1349 sc.varDecl = dsym; // https://issues.dlang.org/show_bug.cgi?id=24051
1350 exp = exp.expressionSemantic(sc);
1351 exp = resolveProperties(sc, exp);
1352 sc = sc.pop();
1353 if (needctfe)
1354 sc = sc.endCTFE();
1355 ei.exp = exp;
1358 Type tb2 = dsym.type.toBasetype();
1359 Type ti = ei.exp.type.toBasetype();
1361 /* The problem is the following code:
1362 * struct CopyTest {
1363 * double x;
1364 * this(double a) { x = a * 10.0;}
1365 * this(this) { x += 2.0; }
1367 * const CopyTest z = CopyTest(5.3); // ok
1368 * const CopyTest w = z; // not ok, postblit not run
1369 * static assert(w.x == 55.0);
1370 * because the postblit doesn't get run on the initialization of w.
1372 if (auto ts = ti.isTypeStruct())
1374 StructDeclaration sd = ts.sym;
1375 /* Look to see if initializer involves a copy constructor
1376 * (which implies a postblit)
1378 // there is a copy constructor
1379 // and exp is the same struct
1380 if (sd.postblit && tb2.toDsymbol(null) == sd)
1382 // The only allowable initializer is a (non-copy) constructor
1383 if (ei.exp.isLvalue())
1384 .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());
1389 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
1390 dsym.inuse--;
1391 if (global.errors > errors)
1393 dsym._init = new ErrorInitializer();
1394 dsym.type = Type.terror;
1397 else
1399 dsym._scope = scx ? scx : sc.copy();
1400 dsym._scope.setNoFree();
1403 sc = sc.pop();
1406 Ldtor:
1407 /* Build code to execute destruction, if necessary
1409 dsym.edtor = dsym.callScopeDtor(sc);
1410 if (dsym.edtor)
1412 if (sc.func && dsym.storage_class & (STC.static_ | STC.gshared))
1413 dsym.edtor = dsym.edtor.expressionSemantic(sc._module._scope);
1414 else
1415 dsym.edtor = dsym.edtor.expressionSemantic(sc);
1417 version (none)
1419 // currently disabled because of std.stdio.stdin, stdout and stderr
1420 if (dsym.isDataseg() && !(dsym.storage_class & STC.extern_))
1421 .error(dsym.loc, "%s `%s` static storage variables cannot have destructors", dsym.kind, dsym.toPrettyChars);
1425 dsym.semanticRun = PASS.semanticdone;
1427 if (dsym.type.toBasetype().ty == Terror)
1428 dsym.errors = true;
1430 if(sc.scopesym && !sc.scopesym.isAggregateDeclaration())
1432 for (ScopeDsymbol sym = sc.scopesym; sym && dsym.endlinnum == 0;
1433 sym = sym.parent ? sym.parent.isScopeDsymbol() : null)
1434 dsym.endlinnum = sym.endlinnum;
1438 override void visit(TypeInfoDeclaration dsym)
1440 assert(dsym._linkage == LINK.c);
1443 override void visit(CAsmDeclaration dsym)
1445 if (dsym.semanticRun >= PASS.semanticdone)
1446 return;
1447 import dmd.iasm : asmSemantic;
1448 asmSemantic(dsym, sc);
1449 dsym.semanticRun = PASS.semanticdone;
1452 override void visit(BitFieldDeclaration dsym)
1454 //printf("BitField::semantic('%s')\n", dsym.toChars());
1455 if (dsym.semanticRun >= PASS.semanticdone)
1456 return;
1458 visit(cast(VarDeclaration)dsym);
1459 if (dsym.errors)
1460 return;
1462 if (!(global.params.bitfields || sc.flags & SCOPE.Cfile))
1464 version (IN_GCC)
1465 .error(dsym.loc, "%s `%s` use `-fpreview=bitfields` for bitfield support", dsym.kind, dsym.toPrettyChars);
1466 else
1467 .error(dsym.loc, "%s `%s` use -preview=bitfields for bitfield support", dsym.kind, dsym.toPrettyChars);
1470 if (!dsym.parent.isStructDeclaration() && !dsym.parent.isClassDeclaration())
1472 .error(dsym.loc, "%s `%s` - bit-field must be member of struct, union, or class", dsym.kind, dsym.toPrettyChars);
1475 sc = sc.startCTFE();
1476 auto width = dsym.width.expressionSemantic(sc);
1477 sc = sc.endCTFE();
1478 width = width.ctfeInterpret();
1479 if (!dsym.type.isintegral())
1481 // C11 6.7.2.1-5
1482 error(width.loc, "bit-field type `%s` is not an integer type", dsym.type.toChars());
1483 dsym.errors = true;
1485 if (!width.isIntegerExp())
1487 error(width.loc, "bit-field width `%s` is not an integer constant", dsym.width.toChars());
1488 dsym.errors = true;
1490 const uwidth = width.toInteger(); // uwidth is unsigned
1491 if (uwidth == 0 && !dsym.isAnonymous())
1493 error(width.loc, "bit-field `%s` has zero width", dsym.toChars());
1494 dsym.errors = true;
1496 const sz = dsym.type.size();
1497 if (sz == SIZE_INVALID)
1498 dsym.errors = true;
1499 const max_width = sz * 8;
1500 if (uwidth > max_width)
1502 error(width.loc, "width `%lld` of bit-field `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
1503 dsym.errors = true;
1505 dsym.fieldWidth = cast(uint)uwidth;
1508 override void visit(Import imp)
1510 static if (LOG)
1512 printf("Import::semantic('%s') %s\n", imp.toPrettyChars(), imp.id.toChars());
1513 scope(exit)
1514 printf("-Import::semantic('%s'), pkg = %p\n", imp.toChars(), imp.pkg);
1516 if (imp.semanticRun > PASS.initial)
1517 return;
1519 if (imp._scope)
1521 sc = imp._scope;
1522 imp._scope = null;
1524 if (!sc)
1525 return;
1527 imp.parent = sc.parent;
1529 imp.semanticRun = PASS.semantic;
1531 // Load if not already done so
1532 if (!imp.mod)
1534 // https://issues.dlang.org/show_bug.cgi?id=22857
1535 // if parser errors occur when loading a module
1536 // we should just stop compilation
1537 if (imp.load(sc))
1539 for (size_t i = 0; i < imp.aliasdecls.length; i++)
1540 imp.aliasdecls[i].type = Type.terror;
1541 return;
1544 if (imp.mod)
1546 imp.mod.importAll(null);
1547 imp.mod.checkImportDeprecation(imp.loc, sc);
1550 if (imp.mod)
1552 // Modules need a list of each imported module
1554 // if inside a template instantiation, the instantianting
1555 // module gets the import.
1556 // https://issues.dlang.org/show_bug.cgi?id=17181
1557 Module importer = sc._module;
1558 if (sc.minst && sc.tinst)
1560 importer = sc.minst;
1561 if (!sc.tinst.importedModules.contains(imp.mod))
1562 sc.tinst.importedModules.push(imp.mod);
1564 //printf("%s imports %s\n", importer.toChars(), imp.mod.toChars());
1565 if (!importer.aimports.contains(imp.mod))
1566 importer.aimports.push(imp.mod);
1568 if (sc.explicitVisibility)
1569 imp.visibility = sc.visibility;
1571 if (!imp.aliasId && !imp.names.length) // neither a selective nor a renamed import
1573 ScopeDsymbol scopesym = sc.getScopesym();
1575 if (!imp.isstatic)
1577 scopesym.importScope(imp.mod, imp.visibility);
1581 imp.addPackageAccess(scopesym);
1584 // if a module has errors it means that parsing has failed.
1585 if (!imp.mod.errors)
1586 imp.mod.dsymbolSemantic(null);
1588 if (imp.mod.needmoduleinfo)
1590 //printf("module4 %s because of %s\n", importer.toChars(), imp.mod.toChars());
1591 importer.needmoduleinfo = 1;
1594 sc = sc.push(imp.mod);
1595 sc.visibility = imp.visibility;
1596 for (size_t i = 0; i < imp.aliasdecls.length; i++)
1598 AliasDeclaration ad = imp.aliasdecls[i];
1599 //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), aliases[i].toChars(), names[i].toChars(), ad._scope);
1600 Dsymbol sym = imp.mod.search(imp.loc, imp.names[i], SearchOpt.ignorePrivateImports);
1601 if (sym)
1603 import dmd.access : symbolIsVisible;
1604 if (!symbolIsVisible(sc, sym) && !sym.errors)
1606 .error(imp.loc, "%s `%s` member `%s` is not visible from module `%s`", imp.mod.kind, imp.mod.toPrettyChars,
1607 imp.names[i].toChars(), sc._module.toChars());
1608 sym.errors = true;
1610 ad.dsymbolSemantic(sc);
1611 // If the import declaration is in non-root module,
1612 // analysis of the aliased symbol is deferred.
1613 // Therefore, don't see the ad.aliassym or ad.type here.
1615 else
1617 Dsymbol s = imp.mod.search_correct(imp.names[i]);
1618 // https://issues.dlang.org/show_bug.cgi?id=23908
1619 // Don't suggest symbols from the importer's module
1620 if (s && s.parent != importer)
1621 .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());
1622 else
1623 .error(imp.loc, "%s `%s` import `%s` not found", imp.mod.kind, imp.mod.toPrettyChars, imp.names[i].toChars());
1624 ad.type = Type.terror;
1627 sc = sc.pop();
1630 imp.semanticRun = PASS.semanticdone;
1632 // object self-imports itself, so skip that
1633 // https://issues.dlang.org/show_bug.cgi?id=7547
1634 // don't list pseudo modules __entrypoint.d, __main.d
1635 // https://issues.dlang.org/show_bug.cgi?id=11117
1636 // https://issues.dlang.org/show_bug.cgi?id=11164
1637 if (global.params.moduleDeps.buffer is null || (imp.id == Id.object && sc._module.ident == Id.object) ||
1638 strcmp(sc._module.ident.toChars(), "__main") == 0)
1639 return;
1641 /* The grammar of the file is:
1642 * ImportDeclaration
1643 * ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
1644 * ModuleAliasIdentifier ] "\n"
1646 * BasicImportDeclaration
1647 * ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
1648 * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
1650 * FilePath
1651 * - any string with '(', ')' and '\' escaped with the '\' character
1653 OutBuffer* ob = global.params.moduleDeps.buffer;
1654 Module imod = sc._module;
1655 if (!global.params.moduleDeps.name)
1656 ob.writestring("depsImport ");
1657 ob.writestring(imod.toPrettyChars());
1658 ob.writestring(" (");
1659 escapePath(ob, imod.srcfile.toChars());
1660 ob.writestring(") : ");
1661 // use visibility instead of sc.visibility because it couldn't be
1662 // resolved yet, see the comment above
1663 visibilityToBuffer(*ob, imp.visibility);
1664 ob.writeByte(' ');
1665 if (imp.isstatic)
1667 stcToBuffer(*ob, STC.static_);
1668 ob.writeByte(' ');
1670 ob.writestring(": ");
1671 foreach (pid; imp.packages)
1673 ob.printf("%s.", pid.toChars());
1675 ob.writestring(imp.id.toString());
1676 ob.writestring(" (");
1677 if (imp.mod)
1678 escapePath(ob, imp.mod.srcfile.toChars());
1679 else
1680 ob.writestring("???");
1681 ob.writeByte(')');
1682 foreach (i, name; imp.names)
1684 if (i == 0)
1685 ob.writeByte(':');
1686 else
1687 ob.writeByte(',');
1688 Identifier _alias = imp.aliases[i];
1689 if (!_alias)
1691 ob.printf("%s", name.toChars());
1692 _alias = name;
1694 else
1695 ob.printf("%s=%s", _alias.toChars(), name.toChars());
1697 if (imp.aliasId)
1698 ob.printf(" -> %s", imp.aliasId.toChars());
1699 ob.writenl();
1702 void attribSemantic(AttribDeclaration ad)
1704 if (ad.semanticRun != PASS.initial)
1705 return;
1706 ad.semanticRun = PASS.semantic;
1707 Dsymbols* d = ad.include(sc);
1708 //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
1709 if (d)
1711 Scope* sc2 = ad.newScope(sc);
1712 bool errors;
1713 for (size_t i = 0; i < d.length; i++)
1715 Dsymbol s = (*d)[i];
1716 s.dsymbolSemantic(sc2);
1717 errors |= s.errors;
1719 ad.errors |= errors;
1720 if (sc2 != sc)
1721 sc2.pop();
1723 ad.semanticRun = PASS.semanticdone;
1726 override void visit(AttribDeclaration atd)
1728 attribSemantic(atd);
1731 override void visit(AnonDeclaration scd)
1733 //printf("\tAnonDeclaration::semantic isunion:%d ptr:%p\n", scd.isunion, scd);
1734 assert(sc.parent);
1735 auto p = sc.parent.pastMixin();
1736 auto ad = p.isAggregateDeclaration();
1737 if (!ad)
1739 error(scd.loc, "%s can only be a part of an aggregate, not %s `%s`", scd.kind(), p.kind(), p.toChars());
1740 scd.errors = true;
1741 return;
1744 if (!scd.decl)
1745 return;
1747 sc = sc.push();
1748 sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
1749 sc.inunion = scd.isunion ? scd : null;
1750 sc.flags = 0;
1751 for (size_t i = 0; i < scd.decl.length; i++)
1753 Dsymbol s = (*scd.decl)[i];
1754 if (auto var = s.isVarDeclaration)
1756 if (scd.isunion)
1757 var.overlapped = true;
1759 s.dsymbolSemantic(sc);
1761 sc = sc.pop();
1764 override void visit(PragmaDeclaration pd)
1766 import dmd.pragmasem : pragmaDeclSemantic;
1767 pragmaDeclSemantic(pd, sc);
1770 override void visit(StaticIfDeclaration sid)
1772 attribSemantic(sid);
1775 override void visit(StaticForeachDeclaration sfd)
1777 attribSemantic(sfd);
1780 private Dsymbols* compileIt(MixinDeclaration cd)
1782 //printf("MixinDeclaration::compileIt(loc = %d) %s\n", cd.loc.linnum, cd.exp.toChars());
1783 OutBuffer buf;
1784 if (expressionsToString(buf, sc, cd.exps))
1785 return null;
1787 const errors = global.errors;
1788 const len = buf.length;
1789 buf.writeByte(0);
1790 const str = buf.extractSlice()[0 .. len];
1791 const bool doUnittests = global.params.parsingUnittestsRequired();
1792 auto loc = adjustLocForMixin(str, cd.loc, global.params.mixinOut);
1793 scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
1794 p.transitionIn = global.params.v.vin;
1795 p.nextToken();
1797 auto d = p.parseDeclDefs(0);
1798 if (global.errors != errors)
1799 return null;
1801 if (p.token.value != TOK.endOfFile)
1803 .error(cd.loc, "%s `%s` incomplete mixin declaration `%s`", cd.kind, cd.toPrettyChars, str.ptr);
1804 return null;
1806 return d;
1809 /***********************************************************
1810 * https://dlang.org/spec/module.html#mixin-declaration
1812 override void visit(MixinDeclaration cd)
1814 //printf("MixinDeclaration::semantic()\n");
1815 if (!cd.compiled)
1817 cd.decl = compileIt(cd);
1818 attribAddMember(cd, sc, cd.scopesym);
1819 cd.compiled = true;
1821 if (cd._scope && cd.decl)
1823 for (size_t i = 0; i < cd.decl.length; i++)
1825 Dsymbol s = (*cd.decl)[i];
1826 s.setScope(cd._scope);
1830 attribSemantic(cd);
1833 override void visit(CPPNamespaceDeclaration ns)
1835 Identifier identFromSE (StringExp se)
1837 const sident = se.toStringz();
1838 if (!sident.length || !Identifier.isValidIdentifier(sident))
1840 error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%.*s`",
1841 cast(int)sident.length, sident.ptr);
1842 return null;
1844 else
1845 return Identifier.idPool(sident);
1848 if (ns.ident !is null)
1849 return attribSemantic(ns);
1851 ns.cppnamespace = sc.namespace;
1852 sc = sc.startCTFE();
1853 ns.exp = ns.exp.expressionSemantic(sc);
1854 ns.exp = resolveProperties(sc, ns.exp);
1855 sc = sc.endCTFE();
1856 ns.exp = ns.exp.ctfeInterpret();
1857 // Can be either a tuple of strings or a string itself
1858 if (auto te = ns.exp.isTupleExp())
1860 expandTuples(te.exps);
1861 CPPNamespaceDeclaration current = ns.cppnamespace;
1862 for (size_t d = 0; d < te.exps.length; ++d)
1864 auto exp = (*te.exps)[d];
1865 auto prev = d ? current : ns.cppnamespace;
1866 current = (d + 1) != te.exps.length
1867 ? new CPPNamespaceDeclaration(ns.loc, exp, null)
1868 : ns;
1869 current.exp = exp;
1870 current.cppnamespace = prev;
1871 if (auto se = exp.toStringExp())
1873 current.ident = identFromSE(se);
1874 if (current.ident is null)
1875 return; // An error happened in `identFromSE`
1877 else
1878 error(ns.exp.loc, "`%s`: index %llu is not a string constant, it is a `%s`",
1879 ns.exp.toChars(), cast(ulong) d, ns.exp.type.toChars());
1882 else if (auto se = ns.exp.toStringExp())
1883 ns.ident = identFromSE(se);
1884 // Empty Tuple
1885 else if (ns.exp.isTypeExp() && ns.exp.isTypeExp().type.toBasetype().isTypeTuple())
1888 else if (!ns.exp.type.isTypeError())
1889 error(ns.exp.loc, "compile time string constant (or sequence) expected, not `%s`",
1890 ns.exp.toChars());
1891 attribSemantic(ns);
1894 override void visit(UserAttributeDeclaration uad)
1896 //printf("UserAttributeDeclaration::semantic() %p\n", this);
1897 if (uad.decl && !uad._scope)
1898 uad.Dsymbol.setScope(sc); // for function local symbols
1899 arrayExpressionSemantic(uad.atts.peekSlice(), sc, true);
1900 return attribSemantic(uad);
1903 override void visit(StaticAssert sa)
1905 if (sa.semanticRun < PASS.semanticdone)
1906 sa.semanticRun = PASS.semanticdone;
1909 override void visit(DebugSymbol ds)
1911 //printf("DebugSymbol::semantic() %s\n", toChars());
1912 if (ds.semanticRun < PASS.semanticdone)
1913 ds.semanticRun = PASS.semanticdone;
1916 override void visit(VersionSymbol vs)
1918 if (vs.semanticRun < PASS.semanticdone)
1919 vs.semanticRun = PASS.semanticdone;
1922 override void visit(Package pkg)
1924 if (pkg.semanticRun < PASS.semanticdone)
1925 pkg.semanticRun = PASS.semanticdone;
1928 override void visit(Module m)
1930 if (m.semanticRun != PASS.initial)
1931 return;
1932 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
1933 m.semanticRun = PASS.semantic;
1934 // Note that modules get their own scope, from scratch.
1935 // This is so regardless of where in the syntax a module
1936 // gets imported, it is unaffected by context.
1937 Scope* sc = m._scope; // see if already got one from importAll()
1938 if (!sc)
1940 sc = Scope.createGlobal(m, global.errorSink); // create root scope
1943 //printf("Module = %p, linkage = %d\n", sc.scopesym, sc.linkage);
1944 // Pass 1 semantic routines: do public side of the definition
1945 m.members.foreachDsymbol( (s)
1947 //printf("\tModule('%s'): '%s'.dsymbolSemantic()\n", toChars(), s.toChars());
1948 s.dsymbolSemantic(sc);
1949 m.runDeferredSemantic();
1952 if (m.userAttribDecl)
1954 m.userAttribDecl.dsymbolSemantic(sc);
1956 if (!m._scope)
1958 sc = sc.pop();
1959 sc.pop(); // 2 pops because Scope.createGlobal() created 2
1961 m.semanticRun = PASS.semanticdone;
1962 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
1965 override void visit(EnumDeclaration ed)
1967 enumSemantic(sc, ed);
1970 override void visit(EnumMember em)
1972 enumMemberSemantic(sc, em);
1975 override void visit(TemplateDeclaration tempdecl)
1977 templateDeclarationSemantic(sc, tempdecl);
1980 override void visit(TemplateInstance ti)
1982 templateInstanceSemantic(ti, sc, ArgumentList());
1985 override void visit(TemplateMixin tm)
1987 static if (LOG)
1989 printf("+TemplateMixin.dsymbolSemantic('%s', this=%p)\n", tm.toChars(), tm);
1990 fflush(stdout);
1992 if (tm.semanticRun != PASS.initial)
1994 // When a class/struct contains mixin members, and is done over
1995 // because of forward references, never reach here so semanticRun
1996 // has been reset to PASS.initial.
1997 static if (LOG)
1999 printf("\tsemantic done\n");
2001 return;
2003 tm.semanticRun = PASS.semantic;
2004 static if (LOG)
2006 printf("\tdo semantic\n");
2009 Scope* scx = null;
2010 if (tm._scope)
2012 sc = tm._scope;
2013 scx = tm._scope; // save so we don't make redundant copies
2014 tm._scope = null;
2017 /* Run semantic on each argument, place results in tiargs[],
2018 * then find best match template with tiargs
2020 if (!tm.findTempDecl(sc) || !tm.semanticTiargs(sc) || !tm.findBestMatch(sc, ArgumentList()))
2022 if (tm.semanticRun == PASS.initial) // forward reference had occurred
2024 //printf("forward reference - deferring\n");
2025 return deferDsymbolSemantic(sc, tm, scx);
2028 tm.inst = tm;
2029 tm.errors = true;
2030 return; // error recovery
2033 auto tempdecl = tm.tempdecl.isTemplateDeclaration();
2034 assert(tempdecl);
2036 if (!tm.ident)
2038 /* Assign scope local unique identifier, as same as lambdas.
2040 const(char)[] s = "__mixin";
2042 if (FuncDeclaration func = sc.parent.isFuncDeclaration())
2044 tm.symtab = func.localsymtab;
2045 if (tm.symtab)
2047 // Inside template constraint, symtab is not set yet.
2048 goto L1;
2051 else
2053 tm.symtab = sc.parent.isScopeDsymbol().symtab;
2055 assert(tm.symtab);
2056 tm.ident = Identifier.generateId(s, tm.symtab.length + 1);
2057 tm.symtab.insert(tm);
2061 tm.inst = tm;
2062 tm.parent = sc.parent;
2064 /* Detect recursive mixin instantiations.
2066 for (Dsymbol s = tm.parent; s; s = s.parent)
2068 //printf("\ts = '%s'\n", s.toChars());
2069 TemplateMixin tmix = s.isTemplateMixin();
2070 if (!tmix || tempdecl != tmix.tempdecl)
2071 continue;
2073 /* Different argument list lengths happen with variadic args
2075 if (tm.tiargs.length != tmix.tiargs.length)
2076 continue;
2078 for (size_t i = 0; i < tm.tiargs.length; i++)
2080 RootObject o = (*tm.tiargs)[i];
2081 Type ta = isType(o);
2082 Expression ea = isExpression(o);
2083 Dsymbol sa = isDsymbol(o);
2084 RootObject tmo = (*tmix.tiargs)[i];
2085 if (ta)
2087 Type tmta = isType(tmo);
2088 if (!tmta)
2089 goto Lcontinue;
2090 if (!ta.equals(tmta))
2091 goto Lcontinue;
2093 else if (ea)
2095 Expression tme = isExpression(tmo);
2096 if (!tme || !ea.equals(tme))
2097 goto Lcontinue;
2099 else if (sa)
2101 Dsymbol tmsa = isDsymbol(tmo);
2102 if (sa != tmsa)
2103 goto Lcontinue;
2105 else
2106 assert(0);
2108 .error(tm.loc, "%s `%s` recursive mixin instantiation", tm.kind, tm.toPrettyChars);
2109 return;
2111 Lcontinue:
2112 continue;
2115 // Copy the syntax trees from the TemplateDeclaration
2116 tm.members = Dsymbol.arraySyntaxCopy(tempdecl.members);
2117 if (!tm.members)
2118 return;
2120 tm.symtab = new DsymbolTable();
2122 sc.getScopesym().importScope(tm, Visibility(Visibility.Kind.public_));
2124 static if (LOG)
2126 printf("\tcreate scope for template parameters '%s'\n", tm.toChars());
2128 Scope* scy = sc.push(tm);
2129 scy.parent = tm;
2131 /* https://issues.dlang.org/show_bug.cgi?id=930
2133 * If the template that is to be mixed in is in the scope of a template
2134 * instance, we have to also declare the type aliases in the new mixin scope.
2136 auto parentInstance = tempdecl.parent ? tempdecl.parent.isTemplateInstance() : null;
2137 if (parentInstance)
2138 parentInstance.declareParameters(scy);
2140 tm.argsym = new ScopeDsymbol();
2141 tm.argsym.parent = scy.parent;
2142 Scope* argscope = scy.push(tm.argsym);
2144 uint errorsave = global.errors;
2146 // Declare each template parameter as an alias for the argument type
2147 tm.declareParameters(argscope);
2149 // Add members to enclosing scope, as well as this scope
2150 tm.members.foreachDsymbol(s => s.addMember(argscope, tm));
2152 // Do semantic() analysis on template instance members
2153 static if (LOG)
2155 printf("\tdo semantic() on template instance members '%s'\n", tm.toChars());
2157 Scope* sc2 = argscope.push(tm);
2158 //size_t deferred_dim = Module.deferred.length;
2160 __gshared int nest;
2161 //printf("%d\n", nest);
2162 if (++nest > global.recursionLimit)
2164 global.gag = 0; // ensure error message gets printed
2165 .error(tm.loc, "%s `%s` recursive expansion", tm.kind, tm.toPrettyChars);
2166 fatal();
2169 tm.members.foreachDsymbol( s => s.setScope(sc2) );
2171 tm.members.foreachDsymbol( s => s.importAll(sc2) );
2173 tm.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
2175 nest--;
2177 /* In DeclDefs scope, TemplateMixin does not have to handle deferred symbols.
2178 * Because the members would already call Module.addDeferredSemantic() for themselves.
2179 * See Struct, Class, Interface, and EnumDeclaration.dsymbolSemantic().
2181 //if (!sc.func && Module.deferred.length > deferred_dim) {}
2183 AggregateDeclaration ad = tm.isMember();
2184 if (sc.func && !ad)
2186 tm.semantic2(sc2);
2187 tm.semantic3(sc2);
2190 // Give additional context info if error occurred during instantiation
2191 if (global.errors != errorsave)
2193 .error(tm.loc, "%s `%s` error instantiating", tm.kind, tm.toPrettyChars);
2194 tm.errors = true;
2197 sc2.pop();
2198 argscope.pop();
2199 scy.pop();
2201 static if (LOG)
2203 printf("-TemplateMixin.dsymbolSemantic('%s', this=%p)\n", tm.toChars(), tm);
2207 override void visit(Nspace ns)
2209 if (ns.semanticRun != PASS.initial)
2210 return;
2211 static if (LOG)
2213 printf("+Nspace::semantic('%s')\n", ns.toChars());
2214 scope(exit) printf("-Nspace::semantic('%s')\n", ns.toChars());
2216 if (ns._scope)
2218 sc = ns._scope;
2219 ns._scope = null;
2221 if (!sc)
2222 return;
2224 bool repopulateMembers = false;
2225 if (ns.identExp)
2227 // resolve the namespace identifier
2228 sc = sc.startCTFE();
2229 Expression resolved = ns.identExp.expressionSemantic(sc);
2230 resolved = resolveProperties(sc, resolved);
2231 sc = sc.endCTFE();
2232 resolved = resolved.ctfeInterpret();
2233 StringExp name = resolved.toStringExp();
2234 TupleExp tup = name ? null : resolved.isTupleExp();
2235 if (!tup && !name)
2237 error(ns.loc, "expected string expression for namespace name, got `%s`", ns.identExp.toChars());
2238 return;
2240 ns.identExp = resolved; // we don't need to keep the old AST around
2241 if (name)
2243 const(char)[] ident = name.toStringz();
2244 if (ident.length == 0 || !Identifier.isValidIdentifier(ident))
2246 error(ns.loc, "expected valid identifier for C++ namespace but got `%.*s`", cast(int)ident.length, ident.ptr);
2247 return;
2249 ns.ident = Identifier.idPool(ident);
2251 else
2253 // create namespace stack from the tuple
2254 Nspace parentns = ns;
2255 foreach (i, exp; *tup.exps)
2257 name = exp.toStringExp();
2258 if (!name)
2260 error(ns.loc, "expected string expression for namespace name, got `%s`", exp.toChars());
2261 return;
2263 const(char)[] ident = name.toStringz();
2264 if (ident.length == 0 || !Identifier.isValidIdentifier(ident))
2266 error(ns.loc, "expected valid identifier for C++ namespace but got `%.*s`", cast(int)ident.length, ident.ptr);
2267 return;
2269 if (i == 0)
2271 ns.ident = Identifier.idPool(ident);
2273 else
2275 // insert the new namespace
2276 Nspace childns = new Nspace(ns.loc, Identifier.idPool(ident), null, parentns.members);
2277 parentns.members = new Dsymbols;
2278 parentns.members.push(childns);
2279 parentns = childns;
2280 repopulateMembers = true;
2286 ns.semanticRun = PASS.semantic;
2287 ns.parent = sc.parent;
2288 // Link does not matter here, if the UDA is present it will error
2289 UserAttributeDeclaration.checkGNUABITag(ns, LINK.cpp);
2291 if (!ns.members)
2293 ns.semanticRun = PASS.semanticdone;
2294 return;
2296 assert(sc);
2297 sc = sc.push(ns);
2298 sc.linkage = LINK.cpp; // note that namespaces imply C++ linkage
2299 sc.parent = ns;
2300 foreach (s; *ns.members)
2302 if (repopulateMembers)
2304 s.addMember(sc, sc.scopesym);
2305 s.setScope(sc);
2307 s.importAll(sc);
2309 foreach (s; *ns.members)
2311 static if (LOG)
2313 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
2315 s.dsymbolSemantic(sc);
2317 sc.pop();
2318 ns.semanticRun = PASS.semanticdone;
2321 /// Do the semantic analysis on the external interface to the function.
2322 override void visit(FuncDeclaration funcdecl)
2324 funcDeclarationSemantic(sc, funcdecl);
2327 override void visit(CtorDeclaration ctd)
2329 //printf("CtorDeclaration::semantic() %s\n", toChars());
2330 if (ctd.semanticRun >= PASS.semanticdone)
2331 return;
2332 if (ctd._scope)
2334 sc = ctd._scope;
2335 ctd._scope = null;
2338 ctd.parent = sc.parent;
2339 Dsymbol p = ctd.toParentDecl();
2340 AggregateDeclaration ad = p.isAggregateDeclaration();
2341 if (!ad)
2343 error(ctd.loc, "constructor can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
2344 ctd.type = Type.terror;
2345 ctd.errors = true;
2346 return;
2349 sc = sc.push();
2351 if (sc.stc & STC.static_)
2353 if (sc.stc & STC.shared_)
2354 error(ctd.loc, "`shared static` has no effect on a constructor inside a `shared static` block. Use `shared static this()`");
2355 else
2356 error(ctd.loc, "`static` has no effect on a constructor inside a `static` block. Use `static this()`");
2359 sc.stc &= ~STC.static_; // not a static constructor
2361 funcDeclarationSemantic(sc, ctd);
2363 sc.pop();
2365 if (ctd.errors)
2366 return;
2368 TypeFunction tf = ctd.type.toTypeFunction();
2369 immutable dim = tf.parameterList.length;
2370 auto sd = ad.isStructDeclaration();
2372 /* See if it's the default constructor
2373 * But, template constructor should not become a default constructor.
2375 if (ad && (!ctd.parent.isTemplateInstance() || ctd.parent.isTemplateMixin()))
2377 if (!sd)
2379 if (dim == 0 && tf.parameterList.varargs == VarArg.none)
2380 ad.defaultCtor = ctd;
2381 return;
2384 if (dim == 0 && tf.parameterList.varargs == VarArg.none) // empty default ctor w/o any varargs
2386 if (ctd.fbody || !(ctd.storage_class & STC.disable))
2388 .error(ctd.loc, "%s `%s` default constructor for structs only allowed " ~
2389 "with `@disable`, no body, and no parameters", ctd.kind, ctd.toPrettyChars);
2390 ctd.storage_class |= STC.disable;
2391 ctd.fbody = null;
2393 sd.noDefaultCtor = true;
2395 else if (dim == 0 && tf.parameterList.varargs != VarArg.none) // allow varargs only ctor
2398 else if (dim && !tf.parameterList.hasArgsWithoutDefault)
2400 if (ctd.storage_class & STC.disable)
2402 .error(ctd.loc, "%s `%s` is marked `@disable`, so it cannot have default "~
2403 "arguments for all parameters.", ctd.kind, ctd.toPrettyChars);
2404 errorSupplemental(ctd.loc, "Use `@disable this();` if you want to disable default initialization.");
2406 else
2407 .error(ctd.loc, "%s `%s` all parameters have default arguments, "~
2408 "but structs cannot have default constructors.", ctd.kind, ctd.toPrettyChars);
2410 else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
2412 //printf("tf: %s\n", tf.toChars());
2413 auto param = tf.parameterList[0];
2414 if (param.storageClass & STC.ref_ && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
2416 //printf("copy constructor\n");
2417 ctd.isCpCtor = true;
2421 // https://issues.dlang.org/show_bug.cgi?id=22593
2422 else if (auto ti = ctd.parent.isTemplateInstance())
2424 checkHasBothRvalueAndCpCtor(sd, ctd, ti);
2428 override void visit(PostBlitDeclaration pbd)
2430 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2431 //printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor);
2432 //printf("stc = x%llx\n", sc.stc);
2433 if (pbd.semanticRun >= PASS.semanticdone)
2434 return;
2435 if (pbd._scope)
2437 sc = pbd._scope;
2438 pbd._scope = null;
2441 pbd.parent = sc.parent;
2442 Dsymbol p = pbd.toParent2();
2443 StructDeclaration ad = p.isStructDeclaration();
2444 if (!ad)
2446 error(pbd.loc, "postblit can only be a member of struct, not %s `%s`", p.kind(), p.toChars());
2447 pbd.type = Type.terror;
2448 pbd.errors = true;
2449 return;
2451 if (pbd.ident == Id.postblit && pbd.semanticRun < PASS.semantic)
2452 ad.postblits.push(pbd);
2453 if (!pbd.type)
2454 pbd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, pbd.storage_class);
2456 sc = sc.push();
2457 sc.stc &= ~STC.static_; // not static
2458 sc.linkage = LINK.d;
2460 funcDeclarationSemantic(sc, pbd);
2462 sc.pop();
2465 override void visit(DtorDeclaration dd)
2467 //printf("DtorDeclaration::semantic() %s\n", dd.toChars());
2468 //printf("ident: %s, %s, %p, %p\n", dd.ident.toChars(), Id.dtor.toChars(), dd.ident, Id.dtor);
2469 if (dd.semanticRun >= PASS.semanticdone)
2470 return;
2471 if (dd._scope)
2473 sc = dd._scope;
2474 dd._scope = null;
2477 dd.parent = sc.parent;
2478 Dsymbol p = dd.toParent2();
2479 AggregateDeclaration ad = p.isAggregateDeclaration();
2480 if (!ad)
2482 error(dd.loc, "destructor can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
2483 dd.type = Type.terror;
2484 dd.errors = true;
2485 return;
2488 if (ad.isClassDeclaration() && ad.classKind == ClassKind.d)
2490 // Class destructors are implicitly `scope`
2491 dd.storage_class |= STC.scope_;
2494 if (dd.ident == Id.dtor && dd.semanticRun < PASS.semantic)
2495 ad.userDtors.push(dd);
2496 if (!dd.type)
2498 dd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, dd.storage_class);
2499 if (ad.classKind == ClassKind.cpp && dd.ident == Id.dtor)
2501 if (auto cldec = ad.isClassDeclaration())
2503 assert (cldec.cppDtorVtblIndex == -1); // double-call check already by dd.type
2504 if (cldec.baseClass && cldec.baseClass.cppDtorVtblIndex != -1)
2506 // override the base virtual
2507 cldec.cppDtorVtblIndex = cldec.baseClass.cppDtorVtblIndex;
2509 else if (!dd.isFinal())
2511 // reserve the dtor slot for the destructor (which we'll create later)
2512 cldec.cppDtorVtblIndex = cast(int)cldec.vtbl.length;
2513 cldec.vtbl.push(dd);
2514 if (target.cpp.twoDtorInVtable)
2515 cldec.vtbl.push(dd); // deleting destructor uses a second slot
2521 sc = sc.push();
2522 sc.stc &= ~STC.static_; // not a static destructor
2523 if (sc.linkage != LINK.cpp)
2524 sc.linkage = LINK.d;
2526 funcDeclarationSemantic(sc, dd);
2528 sc.pop();
2531 override void visit(StaticCtorDeclaration scd)
2533 //printf("StaticCtorDeclaration::semantic()\n");
2534 if (scd.semanticRun >= PASS.semanticdone)
2535 return;
2536 if (scd._scope)
2538 sc = scd._scope;
2539 scd._scope = null;
2542 scd.parent = sc.parent;
2543 Dsymbol p = scd.parent.pastMixin();
2544 if (!p.isScopeDsymbol())
2546 const(char)* s = (scd.isSharedStaticCtorDeclaration() ? "shared " : "");
2547 error(scd.loc, "`%sstatic` constructor can only be member of module/aggregate/template, not %s `%s`", s, p.kind(), p.toChars());
2548 scd.type = Type.terror;
2549 scd.errors = true;
2550 return;
2552 if (!scd.type)
2553 scd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, scd.storage_class);
2555 /* If the static ctor appears within a template instantiation,
2556 * it could get called multiple times by the module constructors
2557 * for different modules. Thus, protect it with a gate.
2559 if (scd.isInstantiated() && scd.semanticRun < PASS.semantic)
2561 /* Add this prefix to the constructor:
2562 * ```
2563 * static int gate;
2564 * if (++gate != 1) return;
2565 * ```
2566 * or, for shared constructor:
2567 * ```
2568 * shared int gate;
2569 * if (core.atomic.atomicOp!"+="(gate, 1) != 1) return;
2570 * ```
2572 const bool isShared = !!scd.isSharedStaticCtorDeclaration();
2573 auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
2574 v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
2576 auto sa = new Statements();
2577 Statement s = new ExpStatement(Loc.initial, v);
2578 sa.push(s);
2580 Expression e;
2581 if (isShared)
2583 e = doAtomicOp("+=", v.ident, IntegerExp.literal!(1));
2584 if (e is null)
2586 .error(scd.loc, "%s `%s` shared static constructor within a template require `core.atomic : atomicOp` to be present", scd.kind, scd.toPrettyChars);
2587 return;
2590 else
2592 e = new AddAssignExp(
2593 Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!1);
2596 e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!1);
2597 s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
2599 sa.push(s);
2600 if (scd.fbody)
2601 sa.push(scd.fbody);
2603 scd.fbody = new CompoundStatement(Loc.initial, sa);
2606 const LINK save = sc.linkage;
2607 if (save != LINK.d)
2609 const(char)* s = (scd.isSharedStaticCtorDeclaration() ? "shared " : "");
2610 deprecation(scd.loc, "`%sstatic` constructor can only be of D linkage", s);
2611 // Just correct it
2612 sc.linkage = LINK.d;
2614 funcDeclarationSemantic(sc, scd);
2615 sc.linkage = save;
2617 // We're going to need ModuleInfo
2618 Module m = scd.getModule();
2619 if (!m)
2620 m = sc._module;
2621 if (m)
2623 m.needmoduleinfo = 1;
2624 //printf("module1 %s needs moduleinfo\n", m.toChars());
2627 foreachUda(scd, sc, (Expression e) {
2628 import dmd.attrib : isEnumAttribute;
2629 if (!isEnumAttribute(e, Id.udaStandalone))
2630 return 0;
2632 if (auto sharedCtor = scd.isSharedStaticCtorDeclaration())
2634 auto trust = sharedCtor.type.isTypeFunction().trust;
2635 if (trust != TRUST.system && trust != TRUST.trusted)
2636 error(e.loc, "a module constructor using `@%s` must be `@system` or `@trusted`", Id.udaStandalone.toChars());
2637 sharedCtor.standalone = true;
2639 else
2640 .error(e.loc, "`@%s` can only be used on shared static constructors", Id.udaStandalone.toChars());
2642 return 1;
2646 override void visit(StaticDtorDeclaration sdd)
2648 if (sdd.semanticRun >= PASS.semanticdone)
2649 return;
2650 if (sdd._scope)
2652 sc = sdd._scope;
2653 sdd._scope = null;
2656 sdd.parent = sc.parent;
2657 Dsymbol p = sdd.parent.pastMixin();
2658 if (!p.isScopeDsymbol())
2660 const(char)* s = (sdd.isSharedStaticDtorDeclaration() ? "shared " : "");
2661 error(sdd.loc, "`%sstatic` destructor can only be member of module/aggregate/template, not %s `%s`", s, p.kind(), p.toChars());
2662 sdd.type = Type.terror;
2663 sdd.errors = true;
2664 return;
2666 if (!sdd.type)
2667 sdd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, sdd.storage_class);
2669 /* If the static ctor appears within a template instantiation,
2670 * it could get called multiple times by the module constructors
2671 * for different modules. Thus, protect it with a gate.
2673 if (sdd.isInstantiated() && sdd.semanticRun < PASS.semantic)
2675 /* Add this prefix to the constructor:
2676 * ```
2677 * static int gate;
2678 * if (--gate != 0) return;
2679 * ```
2680 * or, for shared constructor:
2681 * ```
2682 * shared int gate;
2683 * if (core.atomic.atomicOp!"-="(gate, 1) != 0) return;
2684 * ```
2686 const bool isShared = !!sdd.isSharedStaticDtorDeclaration();
2687 auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
2688 v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
2690 auto sa = new Statements();
2691 Statement s = new ExpStatement(Loc.initial, v);
2692 sa.push(s);
2694 Expression e;
2695 if (isShared)
2697 e = doAtomicOp("-=", v.ident, IntegerExp.literal!(1));
2698 if (e is null)
2700 .error(sdd.loc, "%s `%s` shared static destructo within a template require `core.atomic : atomicOp` to be present", sdd.kind, sdd.toPrettyChars);
2701 return;
2704 else
2706 e = new AddAssignExp(
2707 Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!(-1));
2710 e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!0);
2711 s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
2713 sa.push(s);
2714 if (sdd.fbody)
2715 sa.push(sdd.fbody);
2717 sdd.fbody = new CompoundStatement(Loc.initial, sa);
2719 sdd.vgate = v;
2722 const LINK save = sc.linkage;
2723 if (save != LINK.d)
2725 const(char)* s = (sdd.isSharedStaticDtorDeclaration() ? "shared " : "");
2726 deprecation(sdd.loc, "`%sstatic` destructor can only be of D linkage", s);
2727 // Just correct it
2728 sc.linkage = LINK.d;
2730 funcDeclarationSemantic(sc, sdd);
2731 sc.linkage = save;
2733 // We're going to need ModuleInfo
2734 Module m = sdd.getModule();
2735 if (!m)
2736 m = sc._module;
2737 if (m)
2739 m.needmoduleinfo = 1;
2740 //printf("module2 %s needs moduleinfo\n", m.toChars());
2744 override void visit(InvariantDeclaration invd)
2746 if (invd.semanticRun >= PASS.semanticdone)
2747 return;
2748 if (invd._scope)
2750 sc = invd._scope;
2751 invd._scope = null;
2754 invd.parent = sc.parent;
2755 Dsymbol p = invd.parent.pastMixin();
2756 AggregateDeclaration ad = p.isAggregateDeclaration();
2757 if (!ad)
2759 error(invd.loc, "`invariant` can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
2760 invd.type = Type.terror;
2761 invd.errors = true;
2762 return;
2764 if (invd.ident != Id.classInvariant &&
2765 invd.semanticRun < PASS.semantic &&
2766 !ad.isUnionDeclaration() // users are on their own with union fields
2769 invd.fixupInvariantIdent(ad.invs.length);
2770 ad.invs.push(invd);
2772 if (!invd.type)
2773 invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class);
2775 sc = sc.push();
2776 sc.stc &= ~STC.static_; // not a static invariant
2777 sc.stc |= STC.const_; // invariant() is always const
2778 sc.flags = (sc.flags & ~SCOPE.contract) | SCOPE.invariant_;
2779 sc.linkage = LINK.d;
2781 funcDeclarationSemantic(sc, invd);
2783 sc.pop();
2786 override void visit(UnitTestDeclaration utd)
2788 if (utd.semanticRun >= PASS.semanticdone)
2789 return;
2790 if (utd._scope)
2792 sc = utd._scope;
2793 utd._scope = null;
2796 utd.visibility = sc.visibility;
2798 utd.parent = sc.parent;
2799 Dsymbol p = utd.parent.pastMixin();
2800 if (!p.isScopeDsymbol())
2802 error(utd.loc, "`unittest` can only be a member of module/aggregate/template, not %s `%s`", p.kind(), p.toChars());
2803 utd.type = Type.terror;
2804 utd.errors = true;
2805 return;
2808 if (global.params.useUnitTests)
2810 if (!utd.type)
2811 utd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, utd.storage_class);
2812 Scope* sc2 = sc.push();
2813 sc2.linkage = LINK.d;
2814 funcDeclarationSemantic(sc, utd);
2815 sc2.pop();
2818 version (none)
2820 // We're going to need ModuleInfo even if the unit tests are not
2821 // compiled in, because other modules may import this module and refer
2822 // to this ModuleInfo.
2823 // (This doesn't make sense to me?)
2824 Module m = utd.getModule();
2825 if (!m)
2826 m = sc._module;
2827 if (m)
2829 //printf("module3 %s needs moduleinfo\n", m.toChars());
2830 m.needmoduleinfo = 1;
2835 override void visit(NewDeclaration nd)
2837 //printf("NewDeclaration::semantic()\n");
2838 if (nd.semanticRun >= PASS.semanticdone)
2839 return;
2840 if (!nd.type)
2841 nd.type = new TypeFunction(ParameterList(), Type.tvoid.pointerTo(), LINK.d, nd.storage_class);
2843 funcDeclarationSemantic(sc, nd);
2846 override void visit(StructDeclaration sd)
2848 enum log = false;
2849 if (log) printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
2851 //static int count; if (++count == 20) assert(0);
2853 if (sd.semanticRun >= PASS.semanticdone)
2854 return;
2855 int errors = global.errors;
2857 //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
2858 Scope* scx = null;
2859 if (sd._scope)
2861 sc = sd._scope;
2862 scx = sd._scope; // save so we don't make redundant copies
2863 sd._scope = null;
2866 if (!sd.parent)
2868 assert(sc.parent && sc.func);
2869 sd.parent = sc.parent;
2871 assert(sd.parent && !sd.isAnonymous());
2873 if (sd.errors)
2874 sd.type = Type.terror;
2875 if (sd.semanticRun == PASS.initial)
2876 sd.type = sd.type.addSTC(sc.stc | sd.storage_class);
2877 sd.type = sd.type.typeSemantic(sd.loc, sc);
2878 auto ts = sd.type.isTypeStruct();
2879 if (ts)
2881 if (ts.sym != sd)
2883 TemplateInstance ti = ts.sym.isInstantiated();
2884 if (ti && isError(ti))
2885 ts.sym = sd;
2886 /* For C modules, if module A contains `struct S;` and
2887 * module B contains `struct S { members...}` then replace
2888 * the former with the latter
2890 else if (!ts.sym.members && sd.members)
2891 ts.sym = sd;
2895 // Ungag errors when not speculative
2896 Ungag ungag = sd.ungagSpeculative();
2898 if (sd.semanticRun == PASS.initial)
2900 sd.visibility = sc.visibility;
2902 if (sd.alignment.isUnknown()) // can be set already by `struct __declspec(align(N)) Tag { ... }`
2903 sd.alignment = sc.alignment();
2905 sd.storage_class |= sc.stc;
2906 if (sd.storage_class & STC.abstract_)
2907 .error(sd.loc, "%s `%s` structs, unions cannot be `abstract`", sd.kind, sd.toPrettyChars);
2909 sd.userAttribDecl = sc.userAttribDecl;
2911 if (sc.linkage == LINK.cpp)
2912 sd.classKind = ClassKind.cpp;
2913 else if (sc.linkage == LINK.c)
2914 sd.classKind = ClassKind.c;
2915 sd.cppnamespace = sc.namespace;
2916 sd.cppmangle = sc.cppmangle;
2918 else if (sd.symtab && !scx)
2919 return;
2921 sd.semanticRun = PASS.semantic;
2922 UserAttributeDeclaration.checkGNUABITag(sd, sc.linkage);
2924 if (!sd.members) // if opaque declaration
2926 if (log) printf("\topaque declaration %s\n", sd.toChars());
2927 sd.semanticRun = PASS.semanticdone;
2928 return;
2930 if (!sd.symtab)
2932 sd.symtab = new DsymbolTable();
2934 sd.members.foreachDsymbol( s => s.addMember(sc, sd) );
2937 auto sc2 = sd.newScope(sc);
2939 /* Set scope so if there are forward references, we still might be able to
2940 * resolve individual members like enums.
2942 sd.members.foreachDsymbol( s => s.setScope(sc2) );
2943 sd.members.foreachDsymbol( s => s.importAll(sc2) );
2944 sd.members.foreachDsymbol( (s) { s.dsymbolSemantic(sc2); sd.errors |= s.errors; } );
2946 if (sd.errors)
2947 sd.type = Type.terror;
2949 if (!sd.determineFields())
2951 if (sd.type.ty != Terror)
2953 .error(sd.loc, "%s `%s` circular or forward reference", sd.kind, sd.toPrettyChars);
2954 sd.errors = true;
2955 sd.type = Type.terror;
2958 sc2.pop();
2959 sd.semanticRun = PASS.semanticdone;
2960 return;
2962 /* Following special member functions creation needs semantic analysis
2963 * completion of sub-structs in each field types. For example, buildDtor
2964 * needs to check existence of elaborate dtor in type of each fields.
2965 * See the case in compilable/test14838.d
2967 foreach (v; sd.fields)
2969 Type tb = v.type.baseElemOf();
2970 if (tb.ty != Tstruct)
2971 continue;
2972 auto sdec = (cast(TypeStruct)tb).sym;
2973 if (sdec.semanticRun >= PASS.semanticdone)
2974 continue;
2976 sc2.pop();
2978 if (log) printf("\tdeferring %s\n", sd.toChars());
2979 return deferDsymbolSemantic(sc, sd, scx);
2982 /* Look for special member functions.
2984 sd.disableNew = sd.search(Loc.initial, Id.classNew) !is null;
2986 // Look for the constructor
2987 sd.ctor = sd.searchCtor();
2989 buildDtors(sd, sc2);
2991 sd.hasCopyCtor = buildCopyCtor(sd, sc2);
2992 sd.postblit = buildPostBlit(sd, sc2);
2994 buildOpAssign(sd, sc2);
2995 buildOpEquals(sd, sc2);
2997 if (!(sc2.flags & SCOPE.Cfile) &&
2998 global.params.useTypeInfo && Type.dtypeinfo) // these functions are used for TypeInfo
3000 sd.xeq = buildXopEquals(sd, sc2);
3001 sd.xcmp = buildXopCmp(sd, sc2);
3002 sd.xhash = buildXtoHash(sd, sc2);
3005 sd.inv = buildInv(sd, sc2);
3007 sd.semanticRun = PASS.semanticdone;
3008 if (log) printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
3010 sc2.pop();
3012 if (sd.ctor)
3014 Dsymbol scall = sd.search(Loc.initial, Id.call);
3015 if (scall)
3017 uint xerrors = global.startGagging();
3018 sc = sc.push();
3019 sc.tinst = null;
3020 sc.minst = null;
3021 auto fcall = resolveFuncCall(sd.loc, sc, scall, null, null, ArgumentList(), FuncResolveFlag.quiet);
3022 sc = sc.pop();
3023 global.endGagging(xerrors);
3025 if (fcall && fcall.isStatic())
3027 .error(fcall.loc, "%s `%s` `static opCall` is hidden by constructors and can never be called", sd.kind, sd.toPrettyChars);
3028 errorSupplemental(fcall.loc, "Please use a factory method instead, or replace all constructors with `static opCall`.");
3033 if (ts && ts.sym != sd)
3035 StructDeclaration sym = ts.sym;
3036 if (sd.isCsymbol() && sym.isCsymbol())
3038 /* This is two structs imported from different C files.
3039 * Just ignore sd, the second one. The first one will always
3040 * be found when going through the type.
3043 else
3045 version (none)
3047 printf("this = %p %s\n", sd, sd.toChars());
3048 printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars());
3050 // https://issues.dlang.org/show_bug.cgi?id=19024
3051 .error(sd.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", sd.kind, sd.toPrettyChars, sym.loc.toChars());
3055 if (global.errors != errors)
3057 // The type is no good.
3058 sd.type = Type.terror;
3059 sd.errors = true;
3060 if (sd.deferred)
3061 sd.deferred.errors = true;
3064 if (sd.deferred && !global.gag)
3066 sd.deferred.semantic2(sc);
3067 sd.deferred.semantic3(sc);
3070 version (none)
3072 // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
3073 // Deprecated in 2.100
3074 // Make an error in 2.110
3075 if (sd.storage_class & STC.scope_)
3076 deprecation(sd.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
3078 //printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
3081 void interfaceSemantic(ClassDeclaration cd)
3083 cd.vtblInterfaces = new BaseClasses();
3084 cd.vtblInterfaces.reserve(cd.interfaces.length);
3085 foreach (b; cd.interfaces)
3087 cd.vtblInterfaces.push(b);
3088 b.copyBaseInterfaces(cd.vtblInterfaces);
3092 override void visit(ClassDeclaration cldec)
3094 //printf("ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", cldec.toChars(), cldec.type, cldec.sizeok, this);
3095 //printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : "");
3096 //printf("sc.stc = %x\n", sc.stc);
3098 //{ static int n; if (++n == 20) *(char*)0=0; }
3100 if (cldec.semanticRun >= PASS.semanticdone)
3101 return;
3102 int errors = global.errors;
3104 //printf("+ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
3106 Scope* scx = null;
3107 if (cldec._scope)
3109 sc = cldec._scope;
3110 scx = cldec._scope; // save so we don't make redundant copies
3111 cldec._scope = null;
3114 if (!cldec.parent)
3116 assert(sc.parent);
3117 cldec.parent = sc.parent;
3120 if (cldec.errors)
3121 cldec.type = Type.terror;
3122 if (cldec.semanticRun == PASS.initial)
3123 cldec.type = cldec.type.addSTC(sc.stc | cldec.storage_class);
3124 cldec.type = cldec.type.typeSemantic(cldec.loc, sc);
3125 if (auto tc = cldec.type.isTypeClass())
3126 if (tc.sym != cldec)
3128 auto ti = tc.sym.isInstantiated();
3129 if (ti && isError(ti))
3130 tc.sym = cldec;
3133 // Ungag errors when not speculative
3134 Ungag ungag = cldec.ungagSpeculative();
3136 if (cldec.semanticRun == PASS.initial)
3138 cldec.visibility = sc.visibility;
3140 cldec.storage_class |= sc.stc;
3141 if (cldec.storage_class & STC.auto_)
3142 .error(cldec.loc, "%s `%s` storage class `auto` is invalid when declaring a class, did you mean to use `scope`?", cldec.kind, cldec.toPrettyChars);
3143 if (cldec.storage_class & STC.scope_)
3144 cldec.stack = true;
3145 if (cldec.storage_class & STC.abstract_)
3146 cldec.isabstract = ThreeState.yes;
3148 cldec.userAttribDecl = sc.userAttribDecl;
3150 if (sc.linkage == LINK.cpp)
3151 cldec.classKind = ClassKind.cpp;
3152 cldec.cppnamespace = sc.namespace;
3153 cldec.cppmangle = sc.cppmangle;
3154 if (sc.linkage == LINK.objc)
3155 objc.setObjc(cldec);
3157 else if (cldec.symtab && !scx)
3159 return;
3161 cldec.semanticRun = PASS.semantic;
3162 UserAttributeDeclaration.checkGNUABITag(cldec, sc.linkage);
3163 checkMustUseReserved(cldec);
3165 if (cldec.baseok < Baseok.done)
3167 /* https://issues.dlang.org/show_bug.cgi?id=12078
3168 * https://issues.dlang.org/show_bug.cgi?id=12143
3169 * https://issues.dlang.org/show_bug.cgi?id=15733
3170 * While resolving base classes and interfaces, a base may refer
3171 * the member of this derived class. In that time, if all bases of
3172 * this class can be determined, we can go forward the semantc process
3173 * beyond the Lancestorsdone. To do the recursive semantic analysis,
3174 * temporarily set and unset `_scope` around exp().
3176 T resolveBase(T)(lazy T exp)
3178 if (!scx)
3180 scx = sc.copy();
3181 scx.setNoFree();
3183 static if (!is(T == void))
3185 cldec._scope = scx;
3186 auto r = exp();
3187 cldec._scope = null;
3188 return r;
3190 else
3192 cldec._scope = scx;
3193 exp();
3194 cldec._scope = null;
3198 cldec.baseok = Baseok.start;
3200 // Expand any tuples in baseclasses[]
3201 for (size_t i = 0; i < cldec.baseclasses.length;)
3203 auto b = (*cldec.baseclasses)[i];
3204 b.type = resolveBase(b.type.typeSemantic(cldec.loc, sc));
3206 Type tb = b.type.toBasetype();
3207 if (auto tup = tb.isTypeTuple())
3209 cldec.baseclasses.remove(i);
3210 size_t dim = Parameter.dim(tup.arguments);
3211 for (size_t j = 0; j < dim; j++)
3213 Parameter arg = Parameter.getNth(tup.arguments, j);
3214 b = new BaseClass(arg.type);
3215 cldec.baseclasses.insert(i + j, b);
3218 else
3219 i++;
3222 if (cldec.baseok >= Baseok.done)
3224 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
3225 if (cldec.semanticRun >= PASS.semanticdone)
3226 return;
3227 goto Lancestorsdone;
3230 // See if there's a base class as first in baseclasses[]
3231 if (cldec.baseclasses.length)
3233 BaseClass* b = (*cldec.baseclasses)[0];
3234 Type tb = b.type.toBasetype();
3235 TypeClass tc = tb.isTypeClass();
3236 if (!tc)
3238 if (b.type != Type.terror)
3239 .error(cldec.loc, "%s `%s` base type must be `class` or `interface`, not `%s`", cldec.kind, cldec.toPrettyChars, b.type.toChars());
3240 cldec.baseclasses.remove(0);
3241 goto L7;
3243 if (tc.sym.isDeprecated())
3245 if (!cldec.isDeprecated())
3247 // Deriving from deprecated class makes this one deprecated too
3248 cldec.setDeprecated();
3249 tc.checkDeprecated(cldec.loc, sc);
3252 if (tc.sym.isInterfaceDeclaration())
3253 goto L7;
3255 for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass)
3257 if (cdb == cldec)
3259 .error(cldec.loc, "%s `%s` circular inheritance", cldec.kind, cldec.toPrettyChars);
3260 cldec.baseclasses.remove(0);
3261 goto L7;
3265 /* https://issues.dlang.org/show_bug.cgi?id=11034
3266 * Class inheritance hierarchy
3267 * and instance size of each classes are orthogonal information.
3268 * Therefore, even if tc.sym.sizeof == Sizeok.none,
3269 * we need to set baseClass field for class covariance check.
3271 cldec.baseClass = tc.sym;
3272 b.sym = cldec.baseClass;
3274 if (tc.sym.baseok < Baseok.done)
3275 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
3276 if (tc.sym.baseok < Baseok.done)
3278 //printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars());
3279 if (tc.sym._scope)
3280 Module.addDeferredSemantic(tc.sym);
3281 cldec.baseok = Baseok.none;
3286 // Treat the remaining entries in baseclasses as interfaces
3287 // Check for errors, handle forward references
3288 int multiClassError = cldec.baseClass is null ? 0 : 1;
3290 BCLoop:
3291 for (size_t i = (cldec.baseClass ? 1 : 0); i < cldec.baseclasses.length;)
3293 BaseClass* b = (*cldec.baseclasses)[i];
3294 Type tb = b.type.toBasetype();
3295 TypeClass tc = tb.isTypeClass();
3296 if (!tc || !tc.sym.isInterfaceDeclaration())
3298 // It's a class
3299 if (tc)
3301 if (multiClassError == 0)
3303 .error(cldec.loc,"`%s`: base class must be specified first, " ~
3304 "before any interfaces.", cldec.toPrettyChars());
3305 multiClassError += 1;
3307 else if (multiClassError >= 1)
3309 if(multiClassError == 1)
3310 .error(cldec.loc, "`%s`: multiple class inheritance is not supported." ~
3311 " Use multiple interface inheritance and/or composition.", cldec.toPrettyChars());
3312 multiClassError += 1;
3314 if (tc.sym.fields.length)
3315 errorSupplemental(cldec.loc,"`%s` has fields, consider making it a member of `%s`",
3316 b.type.toChars(), cldec.type.toChars());
3317 else
3318 errorSupplemental(cldec.loc,"`%s` has no fields, consider making it an `interface`",
3319 b.type.toChars());
3322 // It's something else: e.g. `int` in `class Foo : Bar, int { ... }`
3323 else if (b.type != Type.terror)
3325 error(cldec.loc,"`%s`: base type must be `interface`, not `%s`",
3326 cldec.toPrettyChars(), b.type.toChars());
3328 cldec.baseclasses.remove(i);
3329 continue;
3332 // Check for duplicate interfaces
3333 for (size_t j = (cldec.baseClass ? 1 : 0); j < i; j++)
3335 BaseClass* b2 = (*cldec.baseclasses)[j];
3336 if (b2.sym == tc.sym)
3338 .error(cldec.loc, "%s `%s` inherits from duplicate interface `%s`", cldec.kind, cldec.toPrettyChars, b2.sym.toChars());
3339 cldec.baseclasses.remove(i);
3340 continue BCLoop;
3343 if (tc.sym.isDeprecated())
3345 if (!cldec.isDeprecated())
3347 // Deriving from deprecated class makes this one deprecated too
3348 cldec.setDeprecated();
3349 tc.checkDeprecated(cldec.loc, sc);
3353 b.sym = tc.sym;
3355 if (tc.sym.baseok < Baseok.done)
3356 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
3357 if (tc.sym.baseok < Baseok.done)
3359 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
3360 if (tc.sym._scope)
3361 Module.addDeferredSemantic(tc.sym);
3362 cldec.baseok = Baseok.none;
3364 i++;
3366 if (cldec.baseok == Baseok.none)
3368 // Forward referencee of one or more bases, try again later
3369 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
3370 return deferDsymbolSemantic(sc, cldec, scx);
3372 cldec.baseok = Baseok.done;
3374 if (cldec.classKind == ClassKind.objc || (cldec.baseClass && cldec.baseClass.classKind == ClassKind.objc))
3375 cldec.classKind = ClassKind.objc; // Objective-C classes do not inherit from Object
3377 // If no base class, and this is not an Object, use Object as base class
3378 if (!cldec.baseClass && cldec.ident != Id.Object && cldec.object && cldec.classKind == ClassKind.d)
3380 void badObjectDotD()
3382 .error(cldec.loc, "%s `%s` missing or corrupt object.d", cldec.kind, cldec.toPrettyChars);
3383 fatal();
3386 if (!cldec.object || cldec.object.errors)
3387 badObjectDotD();
3389 Type t = cldec.object.type;
3390 t = t.typeSemantic(cldec.loc, sc).toBasetype();
3391 if (t.ty == Terror)
3392 badObjectDotD();
3393 TypeClass tc = t.isTypeClass();
3394 assert(tc);
3396 auto b = new BaseClass(tc);
3397 cldec.baseclasses.shift(b);
3399 cldec.baseClass = tc.sym;
3400 assert(!cldec.baseClass.isInterfaceDeclaration());
3401 b.sym = cldec.baseClass;
3403 if (cldec.baseClass)
3405 if (cldec.baseClass.storage_class & STC.final_)
3406 .error(cldec.loc, "%s `%s` cannot inherit from class `%s` because it is `final`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
3408 // Inherit properties from base class
3409 if (cldec.baseClass.isCOMclass())
3410 cldec.com = true;
3411 if (cldec.baseClass.isCPPclass())
3412 cldec.classKind = ClassKind.cpp;
3413 if (cldec.classKind != cldec.baseClass.classKind)
3414 .error(cldec.loc, "%s `%s` with %s linkage cannot inherit from class `%s` with %s linkage", cldec.kind, cldec.toPrettyChars,
3415 ClassKindToChars(cldec.classKind), cldec.baseClass.toChars(), ClassKindToChars(cldec.baseClass.classKind));
3417 if (cldec.baseClass.stack)
3418 cldec.stack = true;
3419 cldec.enclosing = cldec.baseClass.enclosing;
3420 cldec.storage_class |= cldec.baseClass.storage_class & STC.TYPECTOR;
3423 cldec.interfaces = cldec.baseclasses.tdata()[(cldec.baseClass ? 1 : 0) .. cldec.baseclasses.length];
3424 foreach (b; cldec.interfaces)
3426 // If this is an interface, and it derives from a COM interface,
3427 // then this is a COM interface too.
3428 if (b.sym.isCOMinterface())
3429 cldec.com = true;
3430 if (cldec.classKind == ClassKind.cpp && !b.sym.isCPPinterface())
3432 .error(cldec.loc, "C++ class `%s` cannot implement D interface `%s`",
3433 cldec.toPrettyChars(), b.sym.toPrettyChars());
3436 interfaceSemantic(cldec);
3438 Lancestorsdone:
3439 //printf("\tClassDeclaration.dsymbolSemantic(%s) baseok = %d\n", toChars(), baseok);
3441 if (!cldec.members) // if opaque declaration
3443 cldec.semanticRun = PASS.semanticdone;
3444 return;
3446 if (!cldec.symtab)
3448 cldec.symtab = new DsymbolTable();
3450 /* https://issues.dlang.org/show_bug.cgi?id=12152
3451 * The semantic analysis of base classes should be finished
3452 * before the members semantic analysis of this class, in order to determine
3453 * vtbl in this class. However if a base class refers the member of this class,
3454 * it can be resolved as a normal forward reference.
3455 * Call addMember() and setScope() to make this class members visible from the base classes.
3457 cldec.members.foreachDsymbol( s => s.addMember(sc, cldec) );
3459 auto sc2 = cldec.newScope(sc);
3461 /* Set scope so if there are forward references, we still might be able to
3462 * resolve individual members like enums.
3464 cldec.members.foreachDsymbol( s => s.setScope(sc2) );
3466 sc2.pop();
3469 for (size_t i = 0; i < cldec.baseclasses.length; i++)
3471 BaseClass* b = (*cldec.baseclasses)[i];
3472 Type tb = b.type.toBasetype();
3473 TypeClass tc = tb.isTypeClass();
3474 if (tc.sym.semanticRun < PASS.semanticdone)
3476 // Forward referencee of one or more bases, try again later
3477 if (tc.sym._scope)
3478 Module.addDeferredSemantic(tc.sym);
3479 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
3480 return deferDsymbolSemantic(sc, cldec, scx);
3484 if (cldec.baseok == Baseok.done)
3486 cldec.baseok = Baseok.semanticdone;
3487 objc.setMetaclass(cldec, sc);
3489 // initialize vtbl
3490 if (cldec.baseClass)
3492 if (cldec.classKind == ClassKind.cpp && cldec.baseClass.vtbl.length == 0)
3494 .error(cldec.loc, "%s `%s` C++ base class `%s` needs at least one virtual function", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
3497 // Copy vtbl[] from base class
3498 assert(cldec.vtbl.length == 0);
3499 cldec.vtbl.setDim(cldec.baseClass.vtbl.length);
3500 memcpy(cldec.vtbl.tdata(), cldec.baseClass.vtbl.tdata(), (void*).sizeof * cldec.vtbl.length);
3502 cldec.vthis = cldec.baseClass.vthis;
3503 cldec.vthis2 = cldec.baseClass.vthis2;
3505 else
3507 // No base class, so this is the root of the class hierarchy
3508 cldec.vtbl.setDim(0);
3509 if (cldec.vtblOffset())
3510 cldec.vtbl.push(cldec); // leave room for classinfo as first member
3513 /* If this is a nested class, add the hidden 'this'
3514 * member which is a pointer to the enclosing scope.
3516 if (cldec.vthis) // if inheriting from nested class
3518 // Use the base class's 'this' member
3519 if (cldec.storage_class & STC.static_)
3520 .error(cldec.loc, "%s `%s` static class cannot inherit from nested class `%s`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
3521 if (cldec.toParentLocal() != cldec.baseClass.toParentLocal() &&
3522 (!cldec.toParentLocal() ||
3523 !cldec.baseClass.toParentLocal().getType() ||
3524 !cldec.baseClass.toParentLocal().getType().isBaseOf(cldec.toParentLocal().getType(), null)))
3526 if (cldec.toParentLocal())
3528 .error(cldec.loc, "%s `%s` is nested within `%s`, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
3529 cldec.toParentLocal().toChars(),
3530 cldec.baseClass.toChars(),
3531 cldec.baseClass.toParentLocal().toChars());
3533 else
3535 .error(cldec.loc, "%s `%s` is not nested, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
3536 cldec.baseClass.toChars(),
3537 cldec.baseClass.toParentLocal().toChars());
3540 if (cldec.vthis2)
3542 if (cldec.toParent2() != cldec.baseClass.toParent2() &&
3543 (!cldec.toParent2() ||
3544 !cldec.baseClass.toParent2().getType() ||
3545 !cldec.baseClass.toParent2().getType().isBaseOf(cldec.toParent2().getType(), null)))
3547 if (cldec.toParent2() && cldec.toParent2() != cldec.toParentLocal())
3549 .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,
3550 cldec.toParent2().toChars(),
3551 cldec.baseClass.toChars(),
3552 cldec.baseClass.toParent2().toChars());
3554 else
3556 .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,
3557 cldec.baseClass.toChars(),
3558 cldec.baseClass.toParent2().toChars());
3562 else
3563 cldec.makeNested2();
3565 else
3566 cldec.makeNested();
3569 auto sc2 = cldec.newScope(sc);
3571 cldec.members.foreachDsymbol( s => s.importAll(sc2) );
3573 // Note that members.length can grow due to tuple expansion during semantic()
3574 cldec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
3576 if (!cldec.determineFields())
3578 assert(cldec.type == Type.terror);
3579 sc2.pop();
3580 return;
3582 /* Following special member functions creation needs semantic analysis
3583 * completion of sub-structs in each field types.
3585 foreach (v; cldec.fields)
3587 Type tb = v.type.baseElemOf();
3588 if (tb.ty != Tstruct)
3589 continue;
3590 auto sd = (cast(TypeStruct)tb).sym;
3591 if (sd.semanticRun >= PASS.semanticdone)
3592 continue;
3594 sc2.pop();
3596 //printf("\tdeferring %s\n", toChars());
3597 return deferDsymbolSemantic(sc, cldec, scx);
3600 /* Look for special member functions.
3601 * They must be in this class, not in a base class.
3603 // Can be in base class
3604 cldec.disableNew = cldec.search(Loc.initial, Id.classNew) !is null;
3606 // Look for the constructor
3607 cldec.ctor = cldec.searchCtor();
3609 if (!cldec.ctor && cldec.noDefaultCtor)
3611 // A class object is always created by constructor, so this check is legitimate.
3612 foreach (v; cldec.fields)
3614 if (v.storage_class & STC.nodefaultctor)
3615 error(v.loc, "field `%s` must be initialized in constructor", v.toChars());
3619 // If this class has no constructor, but base class has a default
3620 // ctor, create a constructor:
3621 // this() { }
3622 if (!cldec.ctor && cldec.baseClass && cldec.baseClass.ctor)
3624 auto fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type, ArgumentList(), FuncResolveFlag.quiet);
3625 if (!fd) // try shared base ctor instead
3626 fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type.sharedOf, ArgumentList(), FuncResolveFlag.quiet);
3627 if (fd && !fd.errors)
3629 //printf("Creating default this(){} for class %s\n", toChars());
3630 auto btf = fd.type.toTypeFunction();
3631 auto tf = new TypeFunction(ParameterList(), null, LINK.d, fd.storage_class);
3632 tf.mod = btf.mod;
3633 // Don't copy @safe, ... from the base class constructor and let it be inferred instead
3634 // This is required if other lowerings add code to the generated constructor which
3635 // is less strict (e.g. `preview=dtorfields` might introduce a call to a less qualified dtor)
3637 auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf);
3638 ctor.storage_class |= STC.inference | (fd.storage_class & STC.scope_);
3639 ctor.isGenerated = true;
3640 ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
3642 cldec.members.push(ctor);
3643 ctor.addMember(sc, cldec);
3644 ctor.dsymbolSemantic(sc2);
3646 cldec.ctor = ctor;
3647 cldec.defaultCtor = ctor;
3649 else
3651 .error(cldec.loc, "%s `%s` cannot implicitly generate a default constructor when base class `%s` is missing a default constructor", cldec.kind, cldec.toPrettyChars,
3652 cldec.baseClass.toPrettyChars());
3656 buildDtors(cldec, sc2);
3658 if (cldec.classKind == ClassKind.cpp && cldec.cppDtorVtblIndex != -1)
3660 // now we've built the aggregate destructor, we'll make it virtual and assign it to the reserved vtable slot
3661 cldec.dtor.vtblIndex = cldec.cppDtorVtblIndex;
3662 cldec.vtbl[cldec.cppDtorVtblIndex] = cldec.dtor;
3664 if (target.cpp.twoDtorInVtable)
3666 // TODO: create a C++ compatible deleting destructor (call out to `operator delete`)
3667 // for the moment, we'll call the non-deleting destructor and leak
3668 cldec.vtbl[cldec.cppDtorVtblIndex + 1] = cldec.dtor;
3672 if (auto f = hasIdentityOpAssign(cldec, sc2))
3674 if (!(f.storage_class & STC.disable))
3675 .error(f.loc, "%s `%s` identity assignment operator overload is illegal", cldec.kind, cldec.toPrettyChars);
3678 cldec.inv = buildInv(cldec, sc2);
3680 cldec.semanticRun = PASS.semanticdone;
3681 //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
3683 sc2.pop();
3685 /* isAbstract() is undecidable in some cases because of circular dependencies.
3686 * Now that semantic is finished, get a definitive result, and error if it is not the same.
3688 if (cldec.isabstract != ThreeState.none) // if evaluated it before completion
3690 const isabstractsave = cldec.isabstract;
3691 cldec.isabstract = ThreeState.none;
3692 cldec.isAbstract(); // recalculate
3693 if (cldec.isabstract != isabstractsave)
3695 .error(cldec.loc, "%s `%s` cannot infer `abstract` attribute due to circular dependencies", cldec.kind, cldec.toPrettyChars);
3699 if (cldec.type.ty == Tclass && (cast(TypeClass)cldec.type).sym != cldec)
3701 // https://issues.dlang.org/show_bug.cgi?id=17492
3702 ClassDeclaration cd = (cast(TypeClass)cldec.type).sym;
3703 version (none)
3705 printf("this = %p %s\n", cldec, cldec.toPrettyChars());
3706 printf("type = %d sym = %p, %s\n", cldec.type.ty, cd, cd.toPrettyChars());
3708 .error(cldec.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", cldec.kind, cldec.toPrettyChars, cd.loc.toChars());
3711 if (global.errors != errors || (cldec.baseClass && cldec.baseClass.errors))
3713 // The type is no good, but we should keep the
3714 // the type so that we have more accurate error messages
3715 // See: https://issues.dlang.org/show_bug.cgi?id=23552
3716 cldec.errors = true;
3717 if (cldec.deferred)
3718 cldec.deferred.errors = true;
3721 // Verify fields of a synchronized class are not public
3722 if (cldec.storage_class & STC.synchronized_)
3724 foreach (vd; cldec.fields)
3726 if (!vd.isThisDeclaration() &&
3727 vd.visible() >= Visibility(Visibility.Kind.public_))
3729 .error(vd.loc, "%s `%s` Field members of a `synchronized` class cannot be `%s`", vd.kind, vd.toPrettyChars,
3730 visibilityToChars(vd.visible().kind));
3735 if (cldec.deferred && !global.gag)
3737 cldec.deferred.semantic2(sc);
3738 cldec.deferred.semantic3(sc);
3740 //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
3742 version (none)
3744 // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
3745 // Deprecated in 2.100
3746 // Make an error in 2.110
3747 // Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
3748 if (cldec.storage_class & STC.scope_)
3749 deprecation(cldec.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
3753 override void visit(InterfaceDeclaration idec)
3755 /// Returns: `true` is this is an anonymous Objective-C metaclass
3756 static bool isAnonymousMetaclass(InterfaceDeclaration idec)
3758 return idec.classKind == ClassKind.objc &&
3759 idec.objc.isMeta &&
3760 idec.isAnonymous;
3763 //printf("InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
3764 if (idec.semanticRun >= PASS.semanticdone)
3765 return;
3766 int errors = global.errors;
3768 //printf("+InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
3770 Scope* scx = null;
3771 if (idec._scope)
3773 sc = idec._scope;
3774 scx = idec._scope; // save so we don't make redundant copies
3775 idec._scope = null;
3778 if (!idec.parent)
3780 assert(sc.parent && sc.func);
3781 idec.parent = sc.parent;
3783 // Objective-C metaclasses are anonymous
3784 assert(idec.parent && !idec.isAnonymous || isAnonymousMetaclass(idec));
3786 if (idec.errors)
3787 idec.type = Type.terror;
3788 idec.type = idec.type.typeSemantic(idec.loc, sc);
3789 if (idec.type.ty == Tclass && (cast(TypeClass)idec.type).sym != idec)
3791 auto ti = (cast(TypeClass)idec.type).sym.isInstantiated();
3792 if (ti && isError(ti))
3793 (cast(TypeClass)idec.type).sym = idec;
3796 // Ungag errors when not speculative
3797 Ungag ungag = idec.ungagSpeculative();
3799 if (idec.semanticRun == PASS.initial)
3801 idec.visibility = sc.visibility;
3803 idec.storage_class |= sc.stc;
3804 idec.userAttribDecl = sc.userAttribDecl;
3806 else if (idec.symtab)
3808 if (idec.sizeok == Sizeok.done || !scx)
3810 idec.semanticRun = PASS.semanticdone;
3811 return;
3814 idec.semanticRun = PASS.semantic;
3816 if (idec.baseok < Baseok.done)
3818 T resolveBase(T)(lazy T exp)
3820 if (!scx)
3822 scx = sc.copy();
3823 scx.setNoFree();
3825 static if (!is(T == void))
3827 idec._scope = scx;
3828 auto r = exp();
3829 idec._scope = null;
3830 return r;
3832 else
3834 idec._scope = scx;
3835 exp();
3836 idec._scope = null;
3840 idec.baseok = Baseok.start;
3842 // Expand any tuples in baseclasses[]
3843 for (size_t i = 0; i < idec.baseclasses.length;)
3845 auto b = (*idec.baseclasses)[i];
3846 b.type = resolveBase(b.type.typeSemantic(idec.loc, sc));
3848 Type tb = b.type.toBasetype();
3849 if (auto tup = tb.isTypeTuple())
3851 idec.baseclasses.remove(i);
3852 size_t dim = Parameter.dim(tup.arguments);
3853 for (size_t j = 0; j < dim; j++)
3855 Parameter arg = Parameter.getNth(tup.arguments, j);
3856 b = new BaseClass(arg.type);
3857 idec.baseclasses.insert(i + j, b);
3860 else
3861 i++;
3864 if (idec.baseok >= Baseok.done)
3866 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
3867 if (idec.semanticRun >= PASS.semanticdone)
3868 return;
3869 goto Lancestorsdone;
3872 if (!idec.baseclasses.length && sc.linkage == LINK.cpp)
3873 idec.classKind = ClassKind.cpp;
3874 idec.cppnamespace = sc.namespace;
3875 UserAttributeDeclaration.checkGNUABITag(idec, sc.linkage);
3876 checkMustUseReserved(idec);
3878 if (sc.linkage == LINK.objc)
3879 objc.setObjc(idec);
3881 // Check for errors, handle forward references
3882 BCLoop:
3883 for (size_t i = 0; i < idec.baseclasses.length;)
3885 BaseClass* b = (*idec.baseclasses)[i];
3886 Type tb = b.type.toBasetype();
3887 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null;
3888 if (!tc || !tc.sym.isInterfaceDeclaration())
3890 if (b.type != Type.terror)
3891 .error(idec.loc, "%s `%s` base type must be `interface`, not `%s`", idec.kind, idec.toPrettyChars, b.type.toChars());
3892 idec.baseclasses.remove(i);
3893 continue;
3896 // Check for duplicate interfaces
3897 for (size_t j = 0; j < i; j++)
3899 BaseClass* b2 = (*idec.baseclasses)[j];
3900 if (b2.sym == tc.sym)
3902 .error(idec.loc, "%s `%s` inherits from duplicate interface `%s`", idec.kind, idec.toPrettyChars, b2.sym.toChars());
3903 idec.baseclasses.remove(i);
3904 continue BCLoop;
3907 if (tc.sym == idec || idec.isBaseOf2(tc.sym))
3909 .error(idec.loc, "%s `%s` circular inheritance of interface", idec.kind, idec.toPrettyChars);
3910 idec.baseclasses.remove(i);
3911 continue;
3913 if (tc.sym.isDeprecated())
3915 if (!idec.isDeprecated())
3917 // Deriving from deprecated interface makes this one deprecated too
3918 idec.setDeprecated();
3919 tc.checkDeprecated(idec.loc, sc);
3923 b.sym = tc.sym;
3925 if (tc.sym.baseok < Baseok.done)
3926 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
3927 if (tc.sym.baseok < Baseok.done)
3929 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
3930 if (tc.sym._scope)
3931 Module.addDeferredSemantic(tc.sym);
3932 idec.baseok = Baseok.none;
3934 i++;
3936 if (idec.baseok == Baseok.none)
3938 // Forward referencee of one or more bases, try again later
3939 return deferDsymbolSemantic(sc, idec, scx);
3941 idec.baseok = Baseok.done;
3943 idec.interfaces = idec.baseclasses.tdata()[0 .. idec.baseclasses.length];
3944 foreach (b; idec.interfaces)
3946 // If this is an interface, and it derives from a COM interface,
3947 // then this is a COM interface too.
3948 if (b.sym.isCOMinterface())
3949 idec.com = true;
3950 if (b.sym.isCPPinterface())
3951 idec.classKind = ClassKind.cpp;
3954 interfaceSemantic(idec);
3956 Lancestorsdone:
3958 if (!idec.members) // if opaque declaration
3960 idec.semanticRun = PASS.semanticdone;
3961 return;
3963 if (!idec.symtab)
3964 idec.symtab = new DsymbolTable();
3966 for (size_t i = 0; i < idec.baseclasses.length; i++)
3968 BaseClass* b = (*idec.baseclasses)[i];
3969 Type tb = b.type.toBasetype();
3970 TypeClass tc = tb.isTypeClass();
3971 if (tc.sym.semanticRun < PASS.semanticdone)
3973 // Forward referencee of one or more bases, try again later
3974 if (tc.sym._scope)
3975 Module.addDeferredSemantic(tc.sym);
3976 return deferDsymbolSemantic(sc, idec, scx);
3980 if (idec.baseok == Baseok.done)
3982 idec.baseok = Baseok.semanticdone;
3983 objc.setMetaclass(idec, sc);
3985 // initialize vtbl
3986 if (idec.vtblOffset())
3987 idec.vtbl.push(idec); // leave room at vtbl[0] for classinfo
3989 // Cat together the vtbl[]'s from base interfaces
3990 foreach (i, b; idec.interfaces)
3992 // Skip if b has already appeared
3993 for (size_t k = 0; k < i; k++)
3995 if (b == idec.interfaces[k])
3996 goto Lcontinue;
3999 // Copy vtbl[] from base class
4000 if (b.sym.vtblOffset())
4002 size_t d = b.sym.vtbl.length;
4003 if (d > 1)
4005 idec.vtbl.pushSlice(b.sym.vtbl[1 .. d]);
4008 else
4010 idec.vtbl.append(&b.sym.vtbl);
4013 Lcontinue:
4017 idec.members.foreachDsymbol( s => s.addMember(sc, idec) );
4019 auto sc2 = idec.newScope(sc);
4021 /* Set scope so if there are forward references, we still might be able to
4022 * resolve individual members like enums.
4024 idec.members.foreachDsymbol( s => s.setScope(sc2) );
4026 idec.members.foreachDsymbol( s => s.importAll(sc2) );
4028 idec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
4030 idec.semanticRun = PASS.semanticdone;
4031 //printf("-InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
4033 sc2.pop();
4035 if (global.errors != errors)
4037 // The type is no good.
4038 idec.type = Type.terror;
4041 version (none)
4043 if (type.ty == Tclass && (cast(TypeClass)idec.type).sym != idec)
4045 printf("this = %p %s\n", idec, idec.toChars());
4046 printf("type = %d sym = %p\n", idec.type.ty, (cast(TypeClass)idec.type).sym);
4049 assert(idec.type.ty != Tclass || (cast(TypeClass)idec.type).sym == idec);
4051 version (none)
4053 // @@@DEPRECATED_2.120@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
4054 // Deprecated in 2.087
4055 // Made an error in 2.100, but removal depends on `scope class` being removed too
4056 // Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
4057 if (idec.storage_class & STC.scope_)
4058 error(idec.loc, "`scope` as a type constraint is obsolete. Use `scope` at the usage site.");
4064 Adds dsym as a member of scope sds.
4066 Params:
4067 dsym = dsymbol to inserted
4068 sc = scope where the dsymbol is declared
4069 sds = ScopeDsymbol where dsym is inserted
4071 void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
4073 auto addMemberVisitor = new AddMemberVisitor(sc, sds);
4074 dsym.accept(addMemberVisitor);
4077 private void attribAddMember(AttribDeclaration atb, Scope* sc, ScopeDsymbol sds)
4079 Dsymbols* d = atb.include(sc);
4080 if (d)
4082 Scope* sc2 = atb.newScope(sc);
4083 d.foreachDsymbol( s => s.addMember(sc2, sds) );
4084 if (sc2 != sc)
4085 sc2.pop();
4089 private extern(C++) class AddMemberVisitor : Visitor
4091 alias visit = Visitor.visit;
4093 Scope* sc;
4094 ScopeDsymbol sds;
4096 this(Scope* sc, ScopeDsymbol sds)
4098 this.sc = sc;
4099 this.sds = sds;
4102 override void visit(Dsymbol dsym)
4104 //printf("Dsymbol::addMember('%s')\n", toChars());
4105 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars());
4106 //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab);
4107 dsym.parent = sds;
4108 if (dsym.isAnonymous()) // no name, so can't add it to symbol table
4109 return;
4111 if (!sds.symtabInsert(dsym)) // if name is already defined
4113 if (dsym.isAliasDeclaration() && !dsym._scope)
4114 dsym.setScope(sc);
4115 Dsymbol s2 = sds.symtabLookup(dsym, dsym.ident);
4116 /* https://issues.dlang.org/show_bug.cgi?id=17434
4118 * If we are trying to add an import to the symbol table
4119 * that has already been introduced, then keep the one with
4120 * larger visibility. This is fine for imports because if
4121 * we have multiple imports of the same file, if a single one
4122 * is public then the symbol is reachable.
4124 if (auto i1 = dsym.isImport())
4126 if (auto i2 = s2.isImport())
4128 if (sc.explicitVisibility && sc.visibility > i2.visibility)
4129 sds.symtab.update(dsym);
4133 // If using C tag/prototype/forward declaration rules
4134 if (sc.flags & SCOPE.Cfile && !dsym.isImport())
4136 if (handleTagSymbols(*sc, dsym, s2, sds))
4137 return;
4138 if (handleSymbolRedeclarations(*sc, dsym, s2, sds))
4139 return;
4141 sds.multiplyDefined(Loc.initial, dsym, s2); // ImportC doesn't allow overloading
4142 dsym.errors = true;
4143 return;
4146 if (!s2.overloadInsert(dsym))
4148 sds.multiplyDefined(Loc.initial, dsym, s2);
4149 dsym.errors = true;
4152 if (sds.isAggregateDeclaration() || sds.isEnumDeclaration())
4154 if (dsym.ident == Id.__sizeof ||
4155 !(sc && sc.flags & SCOPE.Cfile) && (dsym.ident == Id.__xalignof || dsym.ident == Id._mangleof))
4157 .error(dsym.loc, "%s `%s` `.%s` property cannot be redefined", dsym.kind, dsym.toPrettyChars, dsym.ident.toChars());
4158 dsym.errors = true;
4164 override void visit(StaticAssert _)
4166 // we didn't add anything
4169 /*****************************
4170 * Add import to sd's symbol table.
4172 override void visit(Import imp)
4174 //printf("Import.addMember(this=%s, sds=%s, sc=%p)\n", imp.toChars(), sds.toChars(), sc);
4175 if (imp.names.length == 0)
4176 return visit(cast(Dsymbol)imp);
4177 if (imp.aliasId)
4178 visit(cast(Dsymbol)imp);
4180 /* Instead of adding the import to sds's symbol table,
4181 * add each of the alias=name pairs
4183 for (size_t i = 0; i < imp.names.length; i++)
4185 Identifier name = imp.names[i];
4186 Identifier _alias = imp.aliases[i];
4187 if (!_alias)
4188 _alias = name;
4189 auto tname = new TypeIdentifier(imp.loc, name);
4190 auto ad = new AliasDeclaration(imp.loc, _alias, tname);
4191 ad._import = imp;
4192 addMember(ad, sc, sds);
4193 imp.aliasdecls.push(ad);
4197 override void visit(AttribDeclaration atb)
4199 attribAddMember(atb, sc, sds);
4202 override void visit(StorageClassDeclaration stcd)
4204 Dsymbols* d = stcd.include(sc);
4205 if (d)
4207 Scope* sc2 = stcd.newScope(sc);
4209 d.foreachDsymbol( (s)
4211 //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars());
4212 // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol)
4213 if (auto decl = s.isDeclaration())
4215 decl.storage_class |= stcd.stc & STC.local;
4216 if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case?
4218 sdecl.stc |= stcd.stc & STC.local;
4221 s.addMember(sc2, sds);
4224 if (sc2 != sc)
4225 sc2.pop();
4229 override void visit(VisibilityDeclaration visd)
4231 if (visd.pkg_identifiers)
4233 Dsymbol tmp;
4234 Package.resolve(visd.pkg_identifiers, &tmp, null);
4235 visd.visibility.pkg = tmp ? tmp.isPackage() : null;
4236 visd.pkg_identifiers = null;
4238 if (visd.visibility.kind == Visibility.Kind.package_ && visd.visibility.pkg && sc._module)
4240 Module m = sc._module;
4242 // https://issues.dlang.org/show_bug.cgi?id=17441
4243 // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if
4244 // each package's .isModule() properites are equal.
4246 // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
4247 // This breaks package declarations of the package in question if they are declared in
4248 // the same package.d file, which _do_ have a module associated with them, and hence a non-null
4249 // isModule()
4250 if (!m.isPackage() || !visd.visibility.pkg.ident.equals(m.isPackage().ident))
4252 Package pkg = m.parent ? m.parent.isPackage() : null;
4253 if (!pkg || !visd.visibility.pkg.isAncestorPackageOf(pkg))
4254 .error(visd.loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", visd.kind(), visd.toPrettyChars(false), m.toPrettyChars(true));
4257 attribAddMember(visd, sc, sds);
4260 override void visit(StaticIfDeclaration sid)
4262 //printf("StaticIfDeclaration::addMember() '%s'\n", sid.toChars());
4263 /* This is deferred until the condition evaluated later (by the include() call),
4264 * so that expressions in the condition can refer to declarations
4265 * in the same scope, such as:
4267 * template Foo(int i)
4269 * const int j = i + 1;
4270 * static if (j == 3)
4271 * const int k;
4274 sid.scopesym = sds;
4278 override void visit(StaticForeachDeclaration sfd)
4280 // used only for caching the enclosing symbol
4281 sfd.scopesym = sds;
4284 /***************************************
4285 * Lazily initializes the scope to forward to.
4287 override void visit(ForwardingAttribDeclaration fad)
4289 fad.sym.parent = sds;
4290 sds = fad.sym;
4291 attribAddMember(fad, sc, fad.sym);
4294 override void visit(MixinDeclaration md)
4296 //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, md.memnum);
4297 md.scopesym = sds;
4300 override void visit(DebugSymbol ds)
4302 //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), ds.toChars());
4303 Module m = sds.isModule();
4304 // Do not add the member to the symbol table,
4305 // just make sure subsequent debug declarations work.
4306 if (ds.ident)
4308 if (!m)
4310 .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
4311 ds.errors = true;
4313 else
4315 if (m.debugidsNot && findCondition(*m.debugidsNot, ds.ident))
4317 .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
4318 ds.errors = true;
4320 if (!m.debugids)
4321 m.debugids = new Identifiers();
4322 m.debugids.push(ds.ident);
4325 else
4327 if (!m)
4329 .error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
4330 ds.errors = true;
4332 else
4333 m.debuglevel = ds.level;
4337 override void visit(VersionSymbol vs)
4339 //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), vs.toChars());
4340 Module m = sds.isModule();
4341 // Do not add the member to the symbol table,
4342 // just make sure subsequent debug declarations work.
4343 if (vs.ident)
4345 VersionCondition.checkReserved(vs.loc, vs.ident.toString());
4346 if (!m)
4348 .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
4349 vs.errors = true;
4351 else
4353 if (m.versionidsNot && findCondition(*m.versionidsNot, vs.ident))
4355 .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
4356 vs.errors = true;
4358 if (!m.versionids)
4359 m.versionids = new Identifiers();
4360 m.versionids.push(vs.ident);
4363 else
4365 if (!m)
4367 .error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
4368 vs.errors = true;
4370 else
4371 m.versionlevel = vs.level;
4375 override void visit(Nspace ns)
4377 visit(cast(Dsymbol)ns);
4379 if (ns.members)
4381 if (!ns.symtab)
4382 ns.symtab = new DsymbolTable();
4383 // The namespace becomes 'imported' into the enclosing scope
4384 for (Scope* sce = sc; 1; sce = sce.enclosing)
4386 ScopeDsymbol sds2 = sce.scopesym;
4387 if (sds2)
4389 sds2.importScope(ns, Visibility(Visibility.Kind.public_));
4390 break;
4393 assert(sc);
4394 sc = sc.push(ns);
4395 sc.linkage = LINK.cpp; // namespaces default to C++ linkage
4396 sc.parent = ns;
4397 ns.members.foreachDsymbol(s => s.addMember(sc, ns));
4398 sc.pop();
4402 override void visit(EnumDeclaration ed)
4404 version (none)
4406 printf("EnumDeclaration::addMember() %s\n", ed.toChars());
4407 for (size_t i = 0; i < ed.members.length; i++)
4409 EnumMember em = (*ed.members)[i].isEnumMember();
4410 printf(" member %s\n", em.toChars());
4413 if (!ed.isAnonymous())
4415 visit(cast(Dsymbol)ed);
4418 addEnumMembersToSymtab(ed, sc, sds);
4422 /*******************************************
4423 * Add members of EnumDeclaration to the symbol table(s).
4424 * Params:
4425 * ed = EnumDeclaration
4426 * sc = context of `ed`
4427 * sds = symbol table that `ed` resides in
4429 void addEnumMembersToSymtab(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
4431 const bool isCEnum = (sc.flags & SCOPE.Cfile) != 0; // it's an ImportC enum
4432 //printf("addEnumMembersToSymtab(ed: %s added: %d Cfile: %d)\n", ed.toChars(), ed.added, isCEnum);
4433 if (ed.added)
4434 return;
4435 ed.added = true;
4437 if (!ed.members)
4438 return;
4440 const bool isAnon = ed.isAnonymous();
4442 if ((isCEnum || isAnon) && !sds.symtab)
4443 sds.symtab = new DsymbolTable();
4445 if ((isCEnum || !isAnon) && !ed.symtab)
4446 ed.symtab = new DsymbolTable();
4448 ed.members.foreachDsymbol( (s)
4450 if (EnumMember em = s.isEnumMember())
4452 //printf("adding EnumMember %s to %s %d\n", em.toChars(), ed.toChars(), isCEnum);
4453 em.ed = ed;
4454 if (isCEnum)
4456 /* C doesn't add the enum member to the symbol table of the enum tag, it adds
4457 * it to the symbol table that the tag is in. This is in contrast to D, where enum
4458 * members become members of the enum tag. To accommodate this, we add
4459 * the enum members to both symbol tables.
4461 em.addMember(sc, ed); // add em to ed's symbol table
4462 em.addMember(sc, sds); // add em to symbol table that ed is in
4463 em.parent = ed; // restore it after previous addMember() changed it
4465 else
4467 em.addMember(sc, isAnon ? sds : ed);
4473 /******************************************************
4474 * Verifies if the given Identifier is a DRuntime hook. It uses the hooks
4475 * defined in `id.d`.
4477 * Params:
4478 * id = Identifier to verify
4479 * Returns:
4480 * true if `id` is a DRuntime hook
4481 * false otherwise
4483 private bool isDRuntimeHook(Identifier id)
4485 return id == Id._d_HookTraceImpl ||
4486 id == Id._d_newclassT || id == Id._d_newclassTTrace ||
4487 id == Id._d_arraycatnTX || id == Id._d_arraycatnTXTrace ||
4488 id == Id._d_newThrowable || id == Id._d_delThrowable ||
4489 id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
4490 id == Id._d_arraysetassign || id == Id._d_arraysetctor ||
4491 id == Id._d_arrayctor ||
4492 id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT ||
4493 id == Id._d_arraysetlengthTTrace ||
4494 id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace ||
4495 id == Id._d_arrayappendcTX;
4498 void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList)
4500 //printf("[%s] TemplateInstance.dsymbolSemantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst.loc.toChars(), tempinst.toChars(), tempinst, global.gag, sc);
4501 version (none)
4503 for (Dsymbol s = tempinst; s; s = s.parent)
4505 printf("\t%s\n", s.toChars());
4507 printf("Scope\n");
4508 for (Scope* scx = sc; scx; scx = scx.enclosing)
4510 printf("\t%s parent %s\n", scx._module ? scx._module.toChars() : "null", scx.parent ? scx.parent.toChars() : "null");
4514 static if (LOG)
4516 printf("\n+TemplateInstance.dsymbolSemantic('%s', this=%p)\n", tempinst.toChars(), tempinst);
4518 if (tempinst.inst) // if semantic() was already run
4520 static if (LOG)
4522 printf("-TemplateInstance.dsymbolSemantic('%s', this=%p) already run\n",
4523 tempinst.inst.toChars(), tempinst.inst);
4525 return;
4527 if (tempinst.semanticRun != PASS.initial)
4529 static if (LOG)
4531 printf("Recursive template expansion\n");
4533 auto ungag = Ungag(global.gag);
4534 if (!tempinst.gagged)
4535 global.gag = 0;
4536 .error(tempinst.loc, "%s `%s` recursive template expansion", tempinst.kind, tempinst.toPrettyChars);
4537 if (tempinst.gagged)
4538 tempinst.semanticRun = PASS.initial;
4539 else
4540 tempinst.inst = tempinst;
4541 tempinst.errors = true;
4542 return;
4545 // Get the enclosing template instance from the scope tinst
4546 tempinst.tinst = sc.tinst;
4548 // Get the instantiating module from the scope minst
4549 tempinst.minst = sc.minst;
4550 // https://issues.dlang.org/show_bug.cgi?id=10920
4551 // If the enclosing function is non-root symbol,
4552 // this instance should be speculative.
4553 if (!tempinst.tinst && sc.func && sc.func.inNonRoot())
4555 tempinst.minst = null;
4558 tempinst.gagged = (global.gag > 0);
4560 tempinst.semanticRun = PASS.semantic;
4562 static if (LOG)
4564 printf("\tdo semantic\n");
4566 /* Find template declaration first,
4567 * then run semantic on each argument (place results in tiargs[]),
4568 * last find most specialized template from overload list/set.
4570 if (!tempinst.findTempDecl(sc, null) || !tempinst.semanticTiargs(sc) || !tempinst.findBestMatch(sc, argumentList))
4572 Lerror:
4573 if (tempinst.gagged)
4575 // https://issues.dlang.org/show_bug.cgi?id=13220
4576 // Roll back status for later semantic re-running
4577 tempinst.semanticRun = PASS.initial;
4579 else
4580 tempinst.inst = tempinst;
4581 tempinst.errors = true;
4582 return;
4584 TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration();
4585 assert(tempdecl);
4587 if (global.params.v.templates)
4588 TemplateStats.incInstance(tempdecl, tempinst, global.params.v.templatesListInstances);
4590 tempdecl.checkDeprecated(tempinst.loc, sc);
4592 // If tempdecl is a mixin, disallow it
4593 if (tempdecl.ismixin)
4595 .error(tempinst.loc, "%s `%s` mixin templates are not regular templates", tempinst.kind, tempinst.toPrettyChars);
4596 goto Lerror;
4599 tempinst.hasNestedArgs(tempinst.tiargs, tempdecl.isstatic);
4600 if (tempinst.errors)
4601 goto Lerror;
4603 // Copy the tempdecl namespace (not the scope one)
4604 tempinst.cppnamespace = tempdecl.cppnamespace;
4605 if (tempinst.cppnamespace)
4606 tempinst.cppnamespace.dsymbolSemantic(sc);
4608 /* Greatly simplified semantic processing for AliasSeq templates
4610 if (tempdecl.isTrivialAliasSeq)
4612 tempinst.inst = tempinst;
4613 return aliasSeqInstanceSemantic(tempinst, sc, tempdecl);
4616 /* Greatly simplified semantic processing for Alias templates
4618 else if (tempdecl.isTrivialAlias)
4620 tempinst.inst = tempinst;
4621 return aliasInstanceSemantic(tempinst, sc, tempdecl);
4625 /* See if there is an existing TemplateInstantiation that already
4626 * implements the typeargs. If so, just refer to that one instead.
4628 tempinst.inst = tempdecl.findExistingInstance(tempinst, argumentList);
4629 TemplateInstance errinst = null;
4630 if (!tempinst.inst)
4632 // So, we need to implement 'this' instance.
4634 else if (tempinst.inst.gagged && !tempinst.gagged && tempinst.inst.errors)
4636 // If the first instantiation had failed, re-run semantic,
4637 // so that error messages are shown.
4638 errinst = tempinst.inst;
4640 else
4642 // It's a match
4643 tempinst.parent = tempinst.inst.parent;
4644 tempinst.errors = tempinst.inst.errors;
4646 // If both this and the previous instantiation were gagged,
4647 // use the number of errors that happened last time.
4648 global.errors += tempinst.errors;
4649 global.gaggedErrors += tempinst.errors;
4651 // If the first instantiation was gagged, but this is not:
4652 if (tempinst.inst.gagged)
4654 // It had succeeded, mark it is a non-gagged instantiation,
4655 // and reuse it.
4656 tempinst.inst.gagged = tempinst.gagged;
4659 tempinst.tnext = tempinst.inst.tnext;
4660 tempinst.inst.tnext = tempinst;
4662 /* A module can have explicit template instance and its alias
4663 * in module scope (e,g, `alias Base64 = Base64Impl!('+', '/');`).
4664 * If the first instantiation 'inst' had happened in non-root module,
4665 * compiler can assume that its instantiated code would be included
4666 * in the separately compiled obj/lib file (e.g. phobos.lib).
4668 * However, if 'this' second instantiation happened in root module,
4669 * compiler might need to invoke its codegen
4670 * (https://issues.dlang.org/show_bug.cgi?id=2500 & https://issues.dlang.org/show_bug.cgi?id=2644).
4671 * But whole import graph is not determined until all semantic pass finished,
4672 * so 'inst' should conservatively finish the semantic3 pass for the codegen.
4674 if (tempinst.minst && tempinst.minst.isRoot() && !(tempinst.inst.minst && tempinst.inst.minst.isRoot()))
4676 /* Swap the position of 'inst' and 'this' in the instantiation graph.
4677 * Then, the primary instance `inst` will be changed to a root instance,
4678 * along with all members of `inst` having their scopes updated.
4680 * Before:
4681 * non-root -> A!() -> B!()[inst] -> C!() { members[non-root] }
4683 * root -> D!() -> B!()[this]
4685 * After:
4686 * non-root -> A!() -> B!()[this]
4688 * root -> D!() -> B!()[inst] -> C!() { members[root] }
4690 Module mi = tempinst.minst;
4691 TemplateInstance ti = tempinst.tinst;
4692 tempinst.minst = tempinst.inst.minst;
4693 tempinst.tinst = tempinst.inst.tinst;
4694 tempinst.inst.minst = mi;
4695 tempinst.inst.tinst = ti;
4697 /* https://issues.dlang.org/show_bug.cgi?id=21299
4698 `minst` has been updated on the primary instance `inst` so it is
4699 now coming from a root module, however all Dsymbol `inst.members`
4700 of the instance still have their `_scope.minst` pointing at the
4701 original non-root module. We must now propagate `minst` to all
4702 members so that forward referenced dependencies that get
4703 instantiated will also be appended to the root module, otherwise
4704 there will be undefined references at link-time. */
4705 extern (C++) final class InstMemberWalker : Visitor
4707 alias visit = Visitor.visit;
4708 TemplateInstance inst;
4710 extern (D) this(TemplateInstance inst) scope @safe
4712 this.inst = inst;
4715 override void visit(Dsymbol d)
4717 if (d._scope)
4718 d._scope.minst = inst.minst;
4721 override void visit(ScopeDsymbol sds)
4723 sds.members.foreachDsymbol( s => s.accept(this) );
4724 visit(cast(Dsymbol)sds);
4727 override void visit(AttribDeclaration ad)
4729 ad.include(null).foreachDsymbol( s => s.accept(this) );
4730 visit(cast(Dsymbol)ad);
4733 override void visit(ConditionalDeclaration cd)
4735 if (cd.condition.inc)
4736 visit(cast(AttribDeclaration)cd);
4737 else
4738 visit(cast(Dsymbol)cd);
4741 scope v = new InstMemberWalker(tempinst.inst);
4742 tempinst.inst.accept(v);
4744 if (!global.params.allInst &&
4745 tempinst.minst) // if inst was not speculative...
4747 assert(!tempinst.minst.isRoot()); // ... it was previously appended to a non-root module
4748 // Append again to the root module members[], so that the instance will
4749 // get codegen chances (depending on `tempinst.inst.needsCodegen()`).
4750 tempinst.inst.appendToModuleMember();
4753 assert(tempinst.inst.memberOf && tempinst.inst.memberOf.isRoot(), "no codegen chances");
4756 // modules imported by an existing instance should be added to the module
4757 // that instantiates the instance.
4758 if (tempinst.minst)
4759 foreach(imp; tempinst.inst.importedModules)
4760 if (!tempinst.minst.aimports.contains(imp))
4761 tempinst.minst.aimports.push(imp);
4763 static if (LOG)
4765 printf("\tit's a match with instance %p, %d\n", tempinst.inst, tempinst.inst.semanticRun);
4767 return;
4769 static if (LOG)
4771 printf("\timplement template instance %s '%s'\n", tempdecl.parent.toChars(), tempinst.toChars());
4772 printf("\ttempdecl %s\n", tempdecl.toChars());
4774 uint errorsave = global.errors;
4776 tempinst.inst = tempinst;
4777 tempinst.parent = tempinst.enclosing ? tempinst.enclosing : tempdecl.parent;
4778 //printf("parent = '%s'\n", parent.kind());
4780 if (global.params.v.templates)
4781 TemplateStats.incUnique(tempdecl, tempinst);
4783 TemplateInstance tempdecl_instance_idx = tempdecl.addInstance(tempinst);
4785 //getIdent();
4787 // Store the place we added it to in target_symbol_list(_idx) so we can
4788 // remove it later if we encounter an error.
4789 Dsymbols* target_symbol_list = tempinst.appendToModuleMember();
4790 size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list.length - 1 : 0;
4792 // Copy the syntax trees from the TemplateDeclaration
4793 tempinst.members = Dsymbol.arraySyntaxCopy(tempdecl.members);
4795 // resolve TemplateThisParameter
4796 for (size_t i = 0; i < tempdecl.parameters.length; i++)
4798 if ((*tempdecl.parameters)[i].isTemplateThisParameter() is null)
4799 continue;
4800 Type t = isType((*tempinst.tiargs)[i]);
4801 assert(t);
4802 if (StorageClass stc = ModToStc(t.mod))
4804 //printf("t = %s, stc = x%llx\n", t.toChars(), stc);
4805 auto s = new Dsymbols();
4806 s.push(new StorageClassDeclaration(stc, tempinst.members));
4807 tempinst.members = s;
4809 break;
4812 // Create our own scope for the template parameters
4813 Scope* _scope = tempdecl._scope;
4814 if (tempdecl.semanticRun == PASS.initial)
4816 .error(tempinst.loc, "%s `%s` template instantiation `%s` forward references template declaration `%s`",
4817 tempinst.kind, tempinst.toPrettyChars, tempinst.toChars(), tempdecl.toChars());
4818 return;
4821 static if (LOG)
4823 printf("\tcreate scope for template parameters '%s'\n", tempinst.toChars());
4825 tempinst.argsym = new ScopeDsymbol();
4826 tempinst.argsym.parent = _scope.parent;
4827 _scope = _scope.push(tempinst.argsym);
4828 _scope.tinst = tempinst;
4829 _scope.minst = tempinst.minst;
4830 //scope.stc = 0;
4832 // Declare each template parameter as an alias for the argument type
4833 Scope* paramscope = _scope.push();
4834 paramscope.stc = 0;
4835 paramscope.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=14169
4836 // template parameters should be public
4837 tempinst.declareParameters(paramscope);
4838 paramscope.pop();
4840 // Add members of template instance to template instance symbol table
4841 //parent = scope.scopesym;
4842 tempinst.symtab = new DsymbolTable();
4844 tempinst.members.foreachDsymbol( (s)
4846 static if (LOG)
4848 printf("\t adding member '%s' %p kind %s to '%s'\n", s.toChars(), s, s.kind(), tempinst.toChars());
4850 s.addMember(_scope, tempinst);
4853 static if (LOG)
4855 printf("adding members done\n");
4858 /* See if there is only one member of template instance, and that
4859 * member has the same name as the template instance.
4860 * If so, this template instance becomes an alias for that member.
4862 //printf("members.length = %d\n", tempinst.members.length);
4863 if (tempinst.members.length)
4865 Dsymbol s;
4866 if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s)
4868 //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
4869 //printf("setting aliasdecl\n");
4870 tempinst.aliasdecl = s;
4874 /* If function template declaration
4876 if (argumentList.length > 0 && tempinst.aliasdecl)
4878 if (auto fd = tempinst.aliasdecl.isFuncDeclaration())
4880 /* Transmit fargs to type so that TypeFunction.dsymbolSemantic() can
4881 * resolve any "auto ref" storage classes.
4883 if (fd.type)
4884 if (auto tf = fd.type.isTypeFunction())
4885 tf.inferenceArguments = argumentList;
4889 // Do semantic() analysis on template instance members
4890 static if (LOG)
4892 printf("\tdo semantic() on template instance members '%s'\n", tempinst.toChars());
4894 Scope* sc2;
4895 sc2 = _scope.push(tempinst);
4896 //printf("enclosing = %d, sc.parent = %s\n", tempinst.enclosing, sc.parent.toChars());
4897 sc2.parent = tempinst;
4898 sc2.tinst = tempinst;
4899 sc2.minst = tempinst.minst;
4900 sc2.stc &= ~STC.deprecated_;
4901 tempinst.tryExpandMembers(sc2);
4903 tempinst.semanticRun = PASS.semanticdone;
4905 /* ConditionalDeclaration may introduce eponymous declaration,
4906 * so we should find it once again after semantic.
4908 if (tempinst.members.length)
4910 Dsymbol s;
4911 if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s)
4913 if (!tempinst.aliasdecl || tempinst.aliasdecl != s)
4915 //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
4916 //printf("setting aliasdecl 2\n");
4917 tempinst.aliasdecl = s;
4922 if (global.errors != errorsave)
4923 goto Laftersemantic;
4925 /* If any of the instantiation members didn't get semantic() run
4926 * on them due to forward references, we cannot run semantic2()
4927 * or semantic3() yet.
4930 bool found_deferred_ad = false;
4931 for (size_t i = 0; i < Module.deferred.length; i++)
4933 Dsymbol sd = Module.deferred[i];
4934 AggregateDeclaration ad = sd.isAggregateDeclaration();
4935 if (ad && ad.parent && ad.parent.isTemplateInstance())
4937 //printf("deferred template aggregate: %s %s\n",
4938 // sd.parent.toChars(), sd.toChars());
4939 found_deferred_ad = true;
4940 if (ad.parent == tempinst)
4942 ad.deferred = tempinst;
4943 break;
4947 if (found_deferred_ad || Module.deferred.length)
4948 goto Laftersemantic;
4951 /* The problem is when to parse the initializer for a variable.
4952 * Perhaps VarDeclaration.dsymbolSemantic() should do it like it does
4953 * for initializers inside a function.
4955 //if (sc.parent.isFuncDeclaration())
4957 /* https://issues.dlang.org/show_bug.cgi?id=782
4958 * this has problems if the classes this depends on
4959 * are forward referenced. Find a way to defer semantic()
4960 * on this template.
4962 tempinst.semantic2(sc2);
4964 if (global.errors != errorsave)
4965 goto Laftersemantic;
4967 if ((sc.func || (sc.flags & SCOPE.fullinst)) && !tempinst.tinst)
4969 /* If a template is instantiated inside function, the whole instantiation
4970 * should be done at that position. But, immediate running semantic3 of
4971 * dependent templates may cause unresolved forward reference.
4972 * https://issues.dlang.org/show_bug.cgi?id=9050
4973 * To avoid the issue, don't run semantic3 until semantic and semantic2 done.
4975 TemplateInstances deferred;
4976 tempinst.deferred = &deferred;
4978 //printf("Run semantic3 on %s\n", toChars());
4980 /* https://issues.dlang.org/show_bug.cgi?id=23965
4981 * DRuntime hooks are not deprecated, but may be used for deprecated
4982 * types. Deprecations are disabled while analysing hooks to avoid
4983 * spurious error messages.
4985 auto saveUseDeprecated = global.params.useDeprecated;
4986 if (sc.isDeprecated() && isDRuntimeHook(tempinst.name))
4987 global.params.useDeprecated = DiagnosticReporting.off;
4989 tempinst.trySemantic3(sc2);
4991 global.params.useDeprecated = saveUseDeprecated;
4993 for (size_t i = 0; i < deferred.length; i++)
4995 //printf("+ run deferred semantic3 on %s\n", deferred[i].toChars());
4996 deferred[i].semantic3(null);
4999 tempinst.deferred = null;
5001 else if (tempinst.tinst)
5003 bool doSemantic3 = false;
5004 FuncDeclaration fd;
5005 if (tempinst.aliasdecl)
5006 fd = tempinst.aliasdecl.toAlias2().isFuncDeclaration();
5008 if (fd)
5010 /* Template function instantiation should run semantic3 immediately
5011 * for attribute inference.
5013 scope fld = fd.isFuncLiteralDeclaration();
5014 if (fld && fld.tok == TOK.reserved)
5015 doSemantic3 = true;
5016 else if (sc.func)
5017 doSemantic3 = true;
5019 else if (sc.func)
5021 /* A lambda function in template arguments might capture the
5022 * instantiated scope context. For the correct context inference,
5023 * all instantiated functions should run the semantic3 immediately.
5024 * See also compilable/test14973.d
5026 foreach (oarg; tempinst.tdtypes)
5028 auto s = getDsymbol(oarg);
5029 if (!s)
5030 continue;
5032 if (auto td = s.isTemplateDeclaration())
5034 if (!td.literal)
5035 continue;
5036 assert(td.members && td.members.length == 1);
5037 s = (*td.members)[0];
5039 if (auto fld = s.isFuncLiteralDeclaration())
5041 if (fld.tok == TOK.reserved)
5043 doSemantic3 = true;
5044 break;
5048 //printf("[%s] %s doSemantic3 = %d\n", tempinst.tinst.loc.toChars(), tempinst.tinst.toChars(), doSemantic3);
5050 if (doSemantic3)
5051 tempinst.trySemantic3(sc2);
5053 TemplateInstance ti = tempinst.tinst;
5054 int nest = 0;
5055 while (ti && !ti.deferred && ti.tinst)
5057 ti = ti.tinst;
5058 if (++nest > global.recursionLimit)
5060 global.gag = 0; // ensure error message gets printed
5061 .error(tempinst.loc, "%s `%s` recursive expansion", tempinst.kind, tempinst.toPrettyChars);
5062 fatal();
5065 if (ti && ti.deferred)
5067 //printf("deferred semantic3 of %p %s, ti = %s, ti.deferred = %p\n", this, toChars(), ti.toChars());
5068 for (size_t i = 0;; i++)
5070 if (i == ti.deferred.length)
5072 ti.deferred.push(tempinst);
5073 break;
5075 if ((*ti.deferred)[i] == tempinst)
5076 break;
5081 if (tempinst.aliasdecl)
5083 /* https://issues.dlang.org/show_bug.cgi?id=13816
5084 * AliasDeclaration tries to resolve forward reference
5085 * twice (See inuse check in AliasDeclaration.toAlias()). It's
5086 * necessary to resolve mutual references of instantiated symbols, but
5087 * it will left a true recursive alias in tuple declaration - an
5088 * AliasDeclaration A refers TupleDeclaration B, and B contains A
5089 * in its elements. To correctly make it an error, we strictly need to
5090 * resolve the alias of eponymous member.
5092 tempinst.aliasdecl = tempinst.aliasdecl.toAlias2();
5094 // stop AliasAssign tuple building
5095 if (auto td = tempinst.aliasdecl.isTupleDeclaration())
5096 td.building = false;
5099 Laftersemantic:
5100 sc2.pop();
5101 _scope.pop();
5103 // Give additional context info if error occurred during instantiation
5104 if (global.errors != errorsave)
5106 if (!tempinst.errors)
5108 if (!tempdecl.literal)
5109 .error(tempinst.loc, "%s `%s` error instantiating", tempinst.kind, tempinst.toPrettyChars);
5110 if (tempinst.tinst)
5111 tempinst.tinst.printInstantiationTrace();
5113 tempinst.errors = true;
5114 if (tempinst.gagged)
5116 // Errors are gagged, so remove the template instance from the
5117 // instance/symbol lists we added it to and reset our state to
5118 // finish clean and so we can try to instantiate it again later
5119 // (see https://issues.dlang.org/show_bug.cgi?id=4302 and https://issues.dlang.org/show_bug.cgi?id=6602).
5120 tempdecl.removeInstance(tempdecl_instance_idx);
5121 if (target_symbol_list)
5123 // Because we added 'this' in the last position above, we
5124 // should be able to remove it without messing other indices up.
5125 assert((*target_symbol_list)[target_symbol_list_idx] == tempinst);
5126 target_symbol_list.remove(target_symbol_list_idx);
5127 tempinst.memberOf = null; // no longer a member
5129 tempinst.semanticRun = PASS.initial;
5130 tempinst.inst = null;
5131 tempinst.symtab = null;
5134 else if (errinst)
5136 /* https://issues.dlang.org/show_bug.cgi?id=14541
5137 * If the previous gagged instance had failed by
5138 * circular references, currrent "error reproduction instantiation"
5139 * might succeed, because of the difference of instantiated context.
5140 * On such case, the cached error instance needs to be overridden by the
5141 * succeeded instance.
5143 //printf("replaceInstance()\n");
5144 assert(errinst.errors);
5145 auto ti1 = TemplateInstanceBox(errinst);
5146 tempdecl.instances.remove(ti1);
5148 auto ti2 = TemplateInstanceBox(tempinst);
5149 tempdecl.instances[ti2] = tempinst;
5152 static if (LOG)
5154 printf("-TemplateInstance.dsymbolSemantic('%s', this=%p)\n", tempinst.toChars(), tempinst);
5158 /******************************************************
5159 * Do template instance semantic for isAliasSeq templates.
5160 * This is a greatly simplified version of templateInstanceSemantic().
5162 private
5163 void aliasSeqInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclaration tempdecl)
5165 //printf("[%s] aliasSeqInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
5166 Scope* paramscope = sc.push();
5167 paramscope.stc = 0;
5168 paramscope.visibility = Visibility(Visibility.Kind.public_);
5170 TemplateTupleParameter ttp = (*tempdecl.parameters)[0].isTemplateTupleParameter();
5171 Tuple va = tempinst.tdtypes[0].isTuple();
5172 Declaration d = new TupleDeclaration(tempinst.loc, ttp.ident, &va.objects);
5173 d.storage_class |= STC.templateparameter;
5174 d.dsymbolSemantic(sc);
5176 paramscope.pop();
5178 tempinst.aliasdecl = d;
5180 tempinst.semanticRun = PASS.semanticdone;
5183 /******************************************************
5184 * Do template instance semantic for isAlias templates.
5185 * This is a greatly simplified version of templateInstanceSemantic().
5187 private
5188 void aliasInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclaration tempdecl)
5190 //printf("[%s] aliasInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
5191 Scope* paramscope = sc.push();
5192 paramscope.stc = 0;
5193 paramscope.visibility = Visibility(Visibility.Kind.public_);
5195 TemplateTypeParameter ttp = (*tempdecl.parameters)[0].isTemplateTypeParameter();
5196 Type ta = tempinst.tdtypes[0].isType();
5197 auto ad = tempdecl.onemember.isAliasDeclaration();
5199 // Note: qualifiers can be in both 'ad.type.mod' and 'ad.storage_class'
5200 Declaration d = new AliasDeclaration(tempinst.loc, ttp.ident, ta.addMod(ad.type.mod));
5201 d.storage_class |= STC.templateparameter | ad.storage_class;
5202 d.dsymbolSemantic(sc);
5204 paramscope.pop();
5206 tempinst.aliasdecl = d;
5208 tempinst.semanticRun = PASS.semanticdone;
5211 // function used to perform semantic on AliasDeclaration
5212 void aliasSemantic(AliasDeclaration ds, Scope* sc)
5214 //printf("AliasDeclaration::semantic() %s\n", ds.toChars());
5216 // as DsymbolSemanticVisitor::visit(AliasDeclaration), in case we're called first.
5217 // see https://issues.dlang.org/show_bug.cgi?id=21001
5218 ds.storage_class |= sc.stc & STC.deprecated_;
5219 ds.visibility = sc.visibility;
5220 ds.userAttribDecl = sc.userAttribDecl;
5222 void normalRet()
5224 ds.inuse = 0;
5225 ds.semanticRun = PASS.semanticdone;
5227 if (auto sx = ds.overnext)
5229 ds.overnext = null;
5230 if (!ds.overloadInsert(sx))
5231 ScopeDsymbol.multiplyDefined(Loc.initial, sx, ds);
5235 void errorRet()
5237 ds.aliassym = null;
5238 ds.type = Type.terror;
5239 ds.inuse = 0;
5240 normalRet();
5243 // preserve the original type
5244 if (!ds.originalType && ds.type)
5245 ds.originalType = ds.type.syntaxCopy();
5247 if (ds.aliassym)
5249 auto fd = ds.aliassym.isFuncLiteralDeclaration();
5250 auto td = ds.aliassym.isTemplateDeclaration();
5251 if (fd || td && td.literal)
5253 if (fd && fd.semanticRun >= PASS.semanticdone)
5254 return normalRet();
5256 Expression e = new FuncExp(ds.loc, ds.aliassym);
5257 e = e.expressionSemantic(sc);
5258 if (auto fe = e.isFuncExp())
5260 ds.aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd;
5261 return normalRet();
5263 else
5264 return errorRet();
5267 if (ds.aliassym.isTemplateInstance())
5268 ds.aliassym.dsymbolSemantic(sc);
5269 return normalRet();
5271 ds.inuse = 1;
5273 // Given:
5274 // alias foo.bar.abc def;
5275 // it is not knowable from the syntax whether `def` is an alias
5276 // for type `foo.bar.abc` or an alias for symbol `foo.bar.abc`. It is up to the semantic()
5277 // pass to distinguish.
5278 // If it is a type, then `.type` is set and getType() will return that
5279 // type. If it is a symbol, then `.aliassym` is set and type is `null` -
5280 // toAlias() will return `.aliassym`
5282 const errors = global.errors;
5283 Type oldtype = ds.type;
5285 // Ungag errors when not instantiated DeclDefs scope alias
5286 auto ungag = Ungag(global.gag);
5287 //printf("%s parent = %s, gag = %d, instantiated = %d\n", ds.toChars(), ds.parent.toChars(), global.gag, ds.isInstantiated() !is null);
5288 if (ds.parent && global.gag && !ds.isInstantiated() && !ds.toParent2().isFuncDeclaration() && (sc.minst || sc.tinst))
5290 //printf("%s type = %s\n", ds.toPrettyChars(), ds.type.toChars());
5291 global.gag = 0;
5294 // https://issues.dlang.org/show_bug.cgi?id=18480
5295 // Detect `alias sym = sym;` to prevent creating loops in overload overnext lists.
5296 if (auto tident = ds.type.isTypeIdentifier())
5298 // Selective imports are allowed to alias to the same name `import mod : sym=sym`.
5299 if (!ds._import)
5301 if (tident.ident is ds.ident && !tident.idents.length)
5303 error(ds.loc, "`alias %s = %s;` cannot alias itself, use a qualified name to create an overload set",
5304 ds.ident.toChars(), tident.ident.toChars());
5305 ds.type = Type.terror;
5309 /* This section is needed because Type.resolve() will:
5310 * const x = 3;
5311 * alias y = x;
5312 * try to convert identifier x to 3.
5314 auto s = ds.type.toDsymbol(sc);
5315 if (errors != global.errors)
5316 return errorRet();
5317 if (s == ds)
5319 .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
5320 return errorRet();
5322 if (!s || !s.isEnumMember())
5324 Type t;
5325 Expression e;
5326 Scope* sc2 = sc;
5327 if (ds.storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.disable))
5329 // For 'ref' to be attached to function types, and picked
5330 // up by Type.resolve(), it has to go into sc.
5331 sc2 = sc.push();
5332 sc2.stc |= ds.storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
5334 ds.type = ds.type.addSTC(ds.storage_class);
5335 ds.type.resolve(ds.loc, sc2, e, t, s);
5336 if (sc2 != sc)
5337 sc2.pop();
5339 if (e) // Try to convert Expression to Dsymbol
5341 // TupleExp is naturally converted to a TupleDeclaration
5342 if (auto te = e.isTupleExp())
5343 s = new TupleDeclaration(te.loc, ds.ident, cast(Objects*)te.exps);
5344 else
5346 s = getDsymbol(e);
5347 if (!s)
5349 if (e.op != EXP.error)
5350 .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
5351 return errorRet();
5355 ds.type = t;
5357 if (s == ds)
5359 assert(global.errors);
5360 return errorRet();
5362 if (s) // it's a symbolic alias
5364 //printf("alias %s resolved to %s %s\n", ds.toChars(), s.kind(), s.toChars());
5365 ds.type = null;
5366 ds.aliassym = s;
5368 else // it's a type alias
5370 //printf("alias %s resolved to type %s\n", ds.toChars(), ds.type.toChars());
5371 ds.type = ds.type.typeSemantic(ds.loc, sc);
5372 ds.aliassym = null;
5375 if (global.gag && errors != global.errors)
5376 return errorRet();
5378 normalRet();
5381 /********************
5382 * Perform semantic on AliasAssignment.
5383 * Has a lot of similarities to aliasSemantic(). Perhaps they should share code.
5385 private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
5387 //printf("AliasAssign::semantic() %p, %s\n", ds, ds.ident.toChars());
5389 void errorRet()
5391 ds.errors = true;
5392 ds.type = Type.terror;
5393 ds.semanticRun = PASS.semanticdone;
5394 return;
5397 /* Find the AliasDeclaration corresponding to ds.
5398 * Returns: AliasDeclaration if found, null if error
5400 AliasDeclaration findAliasDeclaration(AliasAssign ds, Scope* sc)
5402 Dsymbol scopesym;
5403 Dsymbol as = sc.search(ds.loc, ds.ident, scopesym);
5404 if (!as)
5406 .error(ds.loc, "%s `%s` undefined identifier `%s`", ds.kind, ds.toPrettyChars, ds.ident.toChars());
5407 return null;
5409 if (as.errors)
5410 return null;
5412 auto ad = as.isAliasDeclaration();
5413 if (!ad)
5415 .error(ds.loc, "%s `%s` identifier `%s` must be an alias declaration", ds.kind, ds.toPrettyChars, as.toChars());
5416 return null;
5419 if (ad.overnext)
5421 error(ds.loc, "%s `%s` cannot reassign overloaded alias", ds.kind, ds.toPrettyChars);
5422 return null;
5425 // Check constraints on the parent
5426 auto adParent = ad.toParent();
5427 if (adParent != ds.toParent())
5429 if (!adParent)
5430 adParent = ds.toParent();
5431 .error(ds.loc, "`%s` must have same parent `%s` as alias `%s`", ds.ident.toChars(), adParent.toChars(), ad.toChars());
5432 return null;
5434 if (!adParent.isTemplateInstance())
5436 .error(ds.loc, "%s `%s` must be a member of a template", ds.kind, ds.toPrettyChars);
5437 return null;
5440 return ad;
5443 auto aliassym = findAliasDeclaration(ds, sc);
5444 if (!aliassym)
5445 return errorRet();
5447 if (aliassym.adFlags & Declaration.wasRead)
5449 if (!aliassym.errors)
5450 error(ds.loc, "%s was read, so cannot reassign", aliassym.toChars());
5451 aliassym.errors = true;
5452 return errorRet();
5455 aliassym.adFlags |= Declaration.ignoreRead; // temporarilly allow reads of aliassym
5457 const storage_class = sc.stc & (STC.deprecated_ | STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
5459 if (ds.aliassym)
5461 auto fd = ds.aliassym.isFuncLiteralDeclaration();
5462 auto td = ds.aliassym.isTemplateDeclaration();
5463 if (fd && fd.semanticRun >= PASS.semanticdone)
5466 else if (fd || td && td.literal)
5469 Expression e = new FuncExp(ds.loc, ds.aliassym);
5470 e = e.expressionSemantic(sc);
5471 auto fe = e.isFuncExp();
5472 if (!fe)
5473 return errorRet();
5474 ds.aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd;
5476 else if (ds.aliassym.isTemplateInstance())
5477 ds.aliassym.dsymbolSemantic(sc);
5479 aliassym.type = null;
5480 aliassym.aliassym = ds.aliassym;
5481 return;
5484 /* Given:
5485 * abc = def;
5486 * it is not knownable from the syntax whether `def` is a type or a symbol.
5487 * It appears here as `ds.type`. Do semantic analysis on `def` to disambiguate.
5490 const errors = global.errors;
5491 Dsymbol s;
5493 // Try AliasSeq optimization
5494 if (auto ti = ds.type.isTypeInstance())
5496 if (!ti.tempinst.findTempDecl(sc, null))
5497 return errorRet();
5498 if (auto tempinst = isAliasSeq(sc, ti))
5500 s = aliasAssignInPlace(sc, tempinst, aliassym);
5501 if (!s)
5502 return errorRet();
5503 goto Lsymdone;
5507 /* This section is needed because Type.resolve() will:
5508 * const x = 3;
5509 * alias y = x;
5510 * try to convert identifier x to 3.
5512 s = ds.type.toDsymbol(sc);
5513 if (errors != global.errors)
5514 return errorRet();
5515 if (s == aliassym)
5517 .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
5518 return errorRet();
5521 if (!s || !s.isEnumMember())
5523 Type t;
5524 Expression e;
5525 Scope* sc2 = sc;
5526 if (storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable))
5528 // For 'ref' to be attached to function types, and picked
5529 // up by Type.resolve(), it has to go into sc.
5530 sc2 = sc.push();
5531 sc2.stc |= storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
5533 ds.type = ds.type.addSTC(storage_class);
5534 ds.type.resolve(ds.loc, sc2, e, t, s);
5535 if (sc2 != sc)
5536 sc2.pop();
5538 if (e) // Try to convert Expression to Dsymbol
5540 // TupleExp is naturally converted to a TupleDeclaration
5541 if (auto te = e.isTupleExp())
5542 s = new TupleDeclaration(te.loc, ds.ident, cast(Objects*)te.exps);
5543 else
5545 s = getDsymbol(e);
5546 if (!s)
5548 if (e.op != EXP.error)
5549 .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
5550 return errorRet();
5554 ds.type = t;
5556 if (s == aliassym)
5558 assert(global.errors);
5559 return errorRet();
5562 if (s) // it's a symbolic alias
5564 Lsymdone:
5565 //printf("alias %s resolved to %s %s\n", toChars(), s.kind(), s.toChars());
5566 aliassym.type = null;
5567 aliassym.aliassym = s;
5568 aliassym.storage_class |= sc.stc & STC.deprecated_;
5569 aliassym.visibility = sc.visibility;
5570 aliassym.userAttribDecl = sc.userAttribDecl;
5572 else // it's a type alias
5574 //printf("alias %s resolved to type %s\n", toChars(), type.toChars());
5575 aliassym.type = ds.type.typeSemantic(ds.loc, sc);
5576 aliassym.aliassym = null;
5580 aliassym.adFlags &= ~Declaration.ignoreRead;
5582 if (aliassym.type && aliassym.type.ty == Terror ||
5583 global.gag && errors != global.errors)
5585 aliassym.type = Type.terror;
5586 aliassym.aliassym = null;
5587 return errorRet();
5590 ds.semanticRun = PASS.semanticdone;
5593 /***************************************
5594 * Expands template instance arguments inside 'alias assign' target declaration (aliassym),
5595 * instead of inside 'tempinst.tiargs' every time.
5596 * Params:
5597 * tempinst = AliasSeq instance
5598 * aliassym = the AliasDeclaration corresponding to AliasAssign
5599 * Returns:
5600 * null.
5602 private TupleDeclaration aliasAssignInPlace(Scope* sc, TemplateInstance tempinst,
5603 AliasDeclaration aliassym)
5605 // Mark instance with semantic done, not needed but just in case.
5606 tempinst.inst = tempinst;
5607 tempinst.semanticRun = PASS.semanticdone;
5608 TupleDeclaration td;
5609 if (aliassym.type)
5611 // Convert TypeTuple to TupleDeclaration to avoid back and forth allocations
5612 // in the assignment process
5613 if (auto tt = aliassym.type.isTypeTuple())
5615 auto objs = new Objects(tt.arguments.length);
5616 foreach (i, p; *tt.arguments)
5617 (*objs)[i] = p.type;
5618 td = new TupleDeclaration(tempinst.loc, aliassym.ident, objs);
5619 td.storage_class |= STC.templateparameter;
5620 td.building = true;
5621 aliassym.type = null;
5623 else if (aliassym.type.isTypeError())
5624 return null;
5627 else if (auto otd = aliassym.aliassym.isTupleDeclaration())
5629 if (otd.building)
5630 td = otd;
5631 else
5633 td = new TupleDeclaration(tempinst.loc, aliassym.ident, otd.objects.copy());
5634 td.storage_class |= STC.templateparameter;
5635 td.building = true;
5638 // If starting from single element in aliassym (td == null) we need to build the tuple
5639 // after semanticTiargs to keep same semantics (for example a FuncLiteraldeclaration
5640 // template argument is converted to FuncExp)
5641 if (td)
5642 aliassym.aliassym = td;
5643 aliassym.semanticRun = PASS.semanticdone;
5644 if (!TemplateInstance.semanticTiargs(tempinst.loc, sc, tempinst.tiargs, 0, td))
5646 tempinst.errors = true;
5647 return null;
5649 // The alias will stop tuple 'building' mode when used (in AliasDeclaration.toAlias(),
5650 // then TupleDeclaration.getType() will work again)
5651 aliassym.semanticRun = PASS.initial;
5652 if (!td)
5654 td = new TupleDeclaration(tempinst.loc, aliassym.ident, tempinst.tiargs);
5655 td.storage_class |= STC.templateparameter;
5656 td.building = true;
5657 return td;
5660 auto tiargs = tempinst.tiargs;
5661 size_t oldlen = td.objects.length;
5662 size_t origstart;
5663 size_t insertidx;
5664 size_t insertlen;
5665 foreach (i, o; *tiargs)
5667 if (o !is td)
5669 ++insertlen;
5670 continue;
5672 // tuple contains itself (tuple = AliasSeq!(..., tuple, ...))
5673 if (insertlen) // insert any left element before
5675 td.objects.insert(insertidx, (*tiargs)[i - insertlen .. i]);
5676 if (insertidx == 0) // reset original tuple start point
5677 origstart = insertlen;
5678 insertlen = 0;
5680 if (insertidx) // insert tuple if found more than one time
5682 td.objects.reserve(oldlen); // reserve first to assert a valid slice
5683 td.objects.pushSlice((*td.objects)[origstart .. origstart + oldlen]);
5685 insertidx = td.objects.length;
5687 if (insertlen)
5689 if (insertlen != tiargs.length) // insert any left element
5690 td.objects.pushSlice((*tiargs)[$ - insertlen .. $]);
5691 else
5692 // just assign tiargs if tuple = AliasSeq!(nottuple, nottuple...)
5693 td.objects = tempinst.tiargs;
5695 return td;
5698 /***************************************
5699 * Check if a template instance is a trivial AliasSeq but without other overloads.
5700 * We can only be 100% sure of being AliasSeq after running semanticTiargs()
5701 * and findBestMatch() but this optimization must happen before that.
5703 private TemplateInstance isAliasSeq(Scope* sc, TypeInstance ti)
5705 auto tovers = ti.tempinst.tempdecl.isOverloadSet();
5706 foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
5708 Dsymbol dstart = tovers ? tovers.a[oi] : ti.tempinst.tempdecl;
5709 int r = overloadApply(dstart, (Dsymbol s)
5711 auto td = s.isTemplateDeclaration();
5712 if (!td || !td.isTrivialAliasSeq)
5713 return 1;
5714 return 0;
5716 if (r)
5717 return null;
5719 return ti.tempinst;
5722 /***************************************
5723 * Find all instance fields in `ad`, then push them into `fields`.
5725 * Runs semantic() for all instance field variables, but also
5726 * the field types can remain yet not resolved forward references,
5727 * except direct recursive definitions.
5728 * After the process sizeok is set to Sizeok.fwd.
5730 * Params:
5731 * ad = the AggregateDeclaration to examine
5732 * Returns:
5733 * false if any errors occur.
5735 bool determineFields(AggregateDeclaration ad)
5737 if (ad._scope)
5738 dsymbolSemantic(ad, null);
5739 if (ad.sizeok != Sizeok.none)
5740 return true;
5742 //printf("determineFields() %s, fields.length = %d\n", toChars(), fields.length);
5743 // determineFields can be called recursively from one of the fields's v.semantic
5744 ad.fields.setDim(0);
5746 static int func(Dsymbol s, void* ctx)
5748 auto ad = cast(AggregateDeclaration)ctx;
5749 auto v = s.isVarDeclaration();
5750 if (!v)
5751 return 0;
5752 if (v.storage_class & STC.manifest)
5753 return 0;
5755 if (v.semanticRun < PASS.semanticdone)
5756 v.dsymbolSemantic(null);
5757 // Return in case a recursive determineFields triggered by v.semantic already finished
5758 if (ad.sizeok != Sizeok.none)
5759 return 1;
5761 if (v.aliasTuple)
5763 // If this variable was really a tuple, process each element.
5764 return v.aliasTuple.foreachVar(tv => tv.apply(&func, cast(void*) ad));
5767 if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter))
5768 return 0;
5769 if (!v.isField() || v.semanticRun < PASS.semanticdone)
5770 return 1; // unresolvable forward reference
5772 ad.fields.push(v);
5774 if (v.storage_class & STC.ref_)
5775 return 0;
5776 auto tv = v.type.baseElemOf();
5777 if (auto tvs = tv.isTypeStruct())
5779 if (ad == tvs.sym)
5781 const(char)* psz = (v.type.toBasetype().ty == Tsarray) ? "static array of " : "";
5782 .error(ad.loc, "%s `%s` cannot have field `%s` with %ssame struct type", ad.kind, ad.toPrettyChars, v.toChars(), psz);
5783 ad.type = Type.terror;
5784 ad.errors = true;
5785 return 1;
5788 return 0;
5791 if (ad.members)
5793 for (size_t i = 0; i < ad.members.length; i++)
5795 auto s = (*ad.members)[i];
5796 if (s.apply(&func, cast(void *)ad))
5798 if (ad.sizeok != Sizeok.none)
5800 // recursive determineFields already finished
5801 return true;
5803 return false;
5808 if (ad.sizeok != Sizeok.done)
5809 ad.sizeok = Sizeok.fwd;
5811 return true;
5814 /// Do an atomic operation (currently tailored to [shared] static ctors|dtors) needs
5815 private CallExp doAtomicOp (string op, Identifier var, Expression arg)
5817 assert(op == "-=" || op == "+=");
5819 Module mod = Module.loadCoreAtomic();
5820 if (!mod)
5821 return null; // core.atomic couldn't be loaded
5823 const loc = Loc.initial;
5825 Objects* tiargs = new Objects(1);
5826 (*tiargs)[0] = new StringExp(loc, op);
5828 Expressions* args = new Expressions(2);
5829 (*args)[0] = new IdentifierExp(loc, var);
5830 (*args)[1] = arg;
5832 auto sc = new ScopeExp(loc, mod);
5833 auto dti = new DotTemplateInstanceExp(
5834 loc, sc, Id.atomicOp, tiargs);
5836 return CallExp.create(loc, dti, args);
5839 /***************************************************
5840 * Set up loc for a parse of a mixin. Append the input text to the mixin.
5841 * Params:
5842 * input = mixin text
5843 * loc = location to adjust
5844 * mixinOut = sink for mixin text data
5845 * Returns:
5846 * adjusted loc suitable for Parser
5849 Loc adjustLocForMixin(const(char)[] input, ref const Loc loc, ref Output mixinOut)
5851 Loc result;
5852 if (mixinOut.doOutput)
5854 const lines = mixinOut.bufferLines;
5855 writeMixin(input, loc, mixinOut.bufferLines, *mixinOut.buffer);
5856 result = Loc(mixinOut.name.ptr, lines + 2, loc.charnum);
5858 else if (loc.filename)
5860 /* Create a pseudo-filename for the mixin string, as it may not even exist
5861 * in the source file.
5863 auto len = strlen(loc.filename) + 7 + (loc.linnum).sizeof * 3 + 1;
5864 char* filename = cast(char*)mem.xmalloc(len);
5865 snprintf(filename, len, "%s-mixin-%d", loc.filename, cast(int)loc.linnum);
5866 result = Loc(filename, loc.linnum, loc.charnum);
5868 else
5869 result = loc;
5870 return result;
5873 /**************************************
5874 * Append source code text to output for better debugging.
5875 * Canonicalize line endings.
5876 * Params:
5877 * s = source code text
5878 * loc = location of source code text
5879 * lines = line count to update
5880 * output = sink for output
5882 private void writeMixin(const(char)[] s, ref const Loc loc, ref int lines, ref OutBuffer buf)
5884 buf.writestring("// expansion at ");
5885 buf.writestring(loc.toChars());
5886 buf.writenl();
5888 ++lines;
5890 // write by line to create consistent line endings
5891 size_t lastpos = 0;
5892 for (size_t i = 0; i < s.length; ++i)
5894 // detect LF and CRLF
5895 const c = s[i];
5896 if (c == '\n' || (c == '\r' && i+1 < s.length && s[i+1] == '\n'))
5898 buf.writestring(s[lastpos .. i]);
5899 buf.writenl();
5900 ++lines;
5901 if (c == '\r')
5902 ++i;
5903 lastpos = i + 1;
5907 if(lastpos < s.length)
5908 buf.writestring(s[lastpos .. $]);
5910 if (s.length == 0 || s[$-1] != '\n')
5912 buf.writenl(); // ensure empty line after expansion
5913 ++lines;
5915 buf.writenl();
5916 ++lines;
5920 * Check signature of `pragma(printf)` function, print error if invalid.
5922 * printf/scanf-like functions must be of the form:
5923 * extern (C/C++) T printf([parameters...], const(char)* format, ...);
5924 * or:
5925 * extern (C/C++) T vprintf([parameters...], const(char)* format, va_list);
5927 * Params:
5928 * funcdecl = function to check
5929 * f = function type
5930 * sc = scope
5932 void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope* sc)
5934 static bool isPointerToChar(Parameter p)
5936 if (auto tptr = p.type.isTypePointer())
5938 return tptr.next.ty == Tchar;
5940 return false;
5943 bool isVa_list(Parameter p)
5945 return p.type.equals(target.va_listType(funcdecl.loc, sc));
5948 const nparams = f.parameterList.length;
5949 const p = (funcdecl.printf ? Id.printf : Id.scanf).toChars();
5950 if (!(f.linkage == LINK.c || f.linkage == LINK.cpp))
5952 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have `extern(C)` or `extern(C++)` linkage,"
5953 ~" not `extern(%s)`",
5954 p, funcdecl.toChars(), f.linkage.linkageToChars());
5956 if (f.parameterList.varargs == VarArg.variadic)
5958 if (!(nparams >= 1 && isPointerToChar(f.parameterList[nparams - 1])))
5960 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have"
5961 ~ " signature `%s %s([parameters...], const(char)*, ...)` not `%s`",
5962 p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars(), funcdecl.type.toChars());
5965 else if (f.parameterList.varargs == VarArg.none)
5967 if(!(nparams >= 2 && isPointerToChar(f.parameterList[nparams - 2]) &&
5968 isVa_list(f.parameterList[nparams - 1])))
5969 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have"~
5970 " signature `%s %s([parameters...], const(char)*, va_list)`",
5971 p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars());
5973 else
5975 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have C-style variadic `...` or `va_list` parameter",
5976 p, funcdecl.toChars());
5980 /*********************************************
5981 * Search for ident as member of d.
5982 * Params:
5983 * d = dsymbol where ident is searched for
5984 * loc = location to print for error messages
5985 * ident = identifier to search for
5986 * flags = search options
5987 * Returns:
5988 * null if not found
5990 Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags flags = SearchOpt.all)
5992 scope v = new SearchVisitor(loc, ident, flags);
5993 d.accept(v);
5994 return v.result;
5997 Dsymbol search_correct(Dsymbol d, Identifier ident)
5999 /***************************************************
6000 * Search for symbol with correct spelling.
6002 Dsymbol symbol_search_fp(const(char)[] seed, out int cost)
6004 /* If not in the lexer's string table, it certainly isn't in the symbol table.
6005 * Doing this first is a lot faster.
6007 if (!seed.length)
6008 return null;
6009 Identifier id = Identifier.lookup(seed);
6010 if (!id)
6011 return null;
6012 cost = 0; // all the same cost
6013 Dsymbol s = d;
6014 Module.clearCache();
6015 return s.search(Loc.initial, id, SearchOpt.ignoreErrors);
6018 if (global.gag)
6019 return null; // don't do it for speculative compiles; too time consuming
6020 // search for exact name first
6021 if (auto s = d.search(Loc.initial, ident, SearchOpt.ignoreErrors))
6022 return s;
6024 import dmd.root.speller : speller;
6025 return speller!symbol_search_fp(ident.toString());
6028 private extern(C++) class SearchVisitor : Visitor
6030 alias visit = Visitor.visit;
6032 const Loc loc;
6033 Identifier ident;
6034 SearchOptFlags flags;
6035 Dsymbol result;
6037 this(const ref Loc loc, Identifier ident, SearchOptFlags flags)
6039 this.loc = loc;
6040 this.ident = ident;
6041 this.flags = flags;
6044 void setResult(Dsymbol d)
6046 result = d;
6049 override void visit(Dsymbol d)
6051 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", d, d.toChars(), ident.toChars());
6052 return setResult(null);
6055 override void visit(ScopeDsymbol sds)
6057 //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", sds.toChars(), ident.toChars(), flags);
6058 //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
6060 // Look in symbols declared in this module
6061 if (sds.symtab && !(flags & SearchOpt.importsOnly))
6063 //printf(" look in locals\n");
6064 auto s1 = sds.symtab.lookup(ident);
6065 if (s1)
6067 //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
6068 return setResult(s1);
6071 //printf(" not found in locals\n");
6073 // Look in imported scopes
6074 if (!sds.importedScopes)
6075 return setResult(null);
6077 //printf(" look in imports\n");
6078 Dsymbol s = null;
6079 OverloadSet a = null;
6080 // Look in imported modules
6081 for (size_t i = 0; i < sds.importedScopes.length; i++)
6083 // If private import, don't search it
6084 if ((flags & SearchOpt.ignorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_)
6085 continue;
6086 SearchOptFlags sflags = flags & (SearchOpt.ignoreErrors | SearchOpt.ignoreAmbiguous); // remember these in recursive searches
6087 Dsymbol ss = (*sds.importedScopes)[i];
6088 //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
6090 if (ss.isModule())
6092 if (flags & SearchOpt.localsOnly)
6093 continue;
6095 else // mixin template
6097 if (flags & SearchOpt.importsOnly)
6098 continue;
6100 sflags |= SearchOpt.localsOnly;
6103 /* Don't find private members if ss is a module
6105 Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? SearchOpt.ignorePrivateImports : SearchOpt.all));
6106 import dmd.access : symbolIsVisible;
6107 if (!s2 || !(flags & SearchOpt.ignoreVisibility) && !symbolIsVisible(sds, s2))
6108 continue;
6109 if (!s)
6111 s = s2;
6112 if (s && s.isOverloadSet())
6113 a = sds.mergeOverloadSet(ident, a, s);
6115 else if (s2 && s != s2)
6117 if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
6119 /* After following aliases, we found the same
6120 * symbol, so it's not an ambiguity. But if one
6121 * alias is deprecated or less accessible, prefer
6122 * the other.
6124 if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
6125 s = s2;
6127 else
6129 /* Two imports of the same module should be regarded as
6130 * the same.
6132 Import i1 = s.isImport();
6133 Import i2 = s2.isImport();
6134 if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
6136 /* https://issues.dlang.org/show_bug.cgi?id=8668
6137 * Public selective import adds AliasDeclaration in module.
6138 * To make an overload set, resolve aliases in here and
6139 * get actual overload roots which accessible via s and s2.
6141 s = s.toAlias();
6142 s2 = s2.toAlias();
6143 /* If both s2 and s are overloadable (though we only
6144 * need to check s once)
6147 auto so2 = s2.isOverloadSet();
6148 if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
6150 if (symbolIsVisible(sds, s2))
6152 a = sds.mergeOverloadSet(ident, a, s2);
6154 if (!symbolIsVisible(sds, s))
6155 s = s2;
6156 continue;
6159 /* Two different overflow sets can have the same members
6160 * https://issues.dlang.org/show_bug.cgi?id=16709
6162 auto so = s.isOverloadSet();
6163 if (so && so2)
6165 if (so.a.length == so2.a.length)
6167 foreach (j; 0 .. so.a.length)
6169 if (so.a[j] !is so2.a[j])
6170 goto L1;
6172 continue; // the same
6174 { } // different
6178 if (flags & SearchOpt.ignoreAmbiguous) // if return NULL on ambiguity
6179 return setResult(null);
6181 /* If two imports from C import files, pick first one, as C has global name space
6183 if (s.isCsymbol() && s2.isCsymbol())
6184 continue;
6186 if (!(flags & SearchOpt.ignoreErrors))
6187 ScopeDsymbol.multiplyDefined(loc, s, s2);
6188 break;
6193 if (s)
6195 /* Build special symbol if we had multiple finds
6197 if (a)
6199 if (!s.isOverloadSet())
6200 a = sds.mergeOverloadSet(ident, a, s);
6201 s = a;
6203 //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
6204 return setResult(s);
6206 //printf(" not found in imports\n");
6207 return setResult(null);
6210 override void visit(WithScopeSymbol ws)
6212 //printf("WithScopeSymbol.search(%s)\n", ident.toChars());
6213 if (flags & SearchOpt.importsOnly)
6214 return setResult(null);
6215 // Acts as proxy to the with class declaration
6216 Dsymbol s = null;
6217 Expression eold = null;
6218 for (Expression e = ws.withstate.exp; e && e != eold; e = resolveAliasThis(ws._scope, e, true))
6220 if (auto se = e.isScopeExp())
6222 s = se.sds;
6224 else if (e.isTypeExp())
6226 s = e.type.toDsymbol(null);
6228 else
6230 Type t = e.type.toBasetype();
6231 s = t.toDsymbol(null);
6233 if (s)
6235 s = s.search(loc, ident, flags);
6236 if (s)
6237 return setResult(s);
6239 eold = e;
6241 return setResult(null);
6244 override void visit(ArrayScopeSymbol ass)
6246 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
6247 if (ident != Id.dollar)
6248 return setResult(null);
6250 VarDeclaration* pvar;
6251 Expression ce;
6253 static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
6256 /* $ gives the number of type entries in the type tuple
6258 auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
6259 Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
6260 v._init = new ExpInitializer(Loc.initial, e);
6261 v.storage_class |= STC.temp | STC.static_ | STC.const_;
6262 v.dsymbolSemantic(sc);
6263 return v;
6266 const DYNCAST kind = ass.arrayContent.dyncast();
6267 switch (kind) with (DYNCAST)
6269 case dsymbol:
6270 TupleDeclaration td = cast(TupleDeclaration) ass.arrayContent;
6271 /* $ gives the number of elements in the tuple
6273 auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
6274 Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
6275 v._init = new ExpInitializer(Loc.initial, e);
6276 v.storage_class |= STC.temp | STC.static_ | STC.const_;
6277 v.dsymbolSemantic(ass._scope);
6278 return setResult(v);
6279 case type:
6280 return setResult(dollarFromTypeTuple(loc, cast(TypeTuple) ass.arrayContent, ass._scope));
6281 default:
6282 break;
6284 Expression exp = cast(Expression) ass.arrayContent;
6285 if (auto ie = exp.isIndexExp())
6287 /* array[index] where index is some function of $
6289 pvar = &ie.lengthVar;
6290 ce = ie.e1;
6292 else if (auto se = exp.isSliceExp())
6294 /* array[lwr .. upr] where lwr or upr is some function of $
6296 pvar = &se.lengthVar;
6297 ce = se.e1;
6299 else if (auto ae = exp.isArrayExp())
6301 /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
6302 * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
6304 pvar = &ae.lengthVar;
6305 ce = ae.e1;
6307 else
6309 /* Didn't find $, look in enclosing scope(s).
6311 return setResult(null);
6313 ce = ce.lastComma();
6314 /* If we are indexing into an array that is really a type
6315 * tuple, rewrite this as an index into a type tuple and
6316 * try again.
6318 if (auto te = ce.isTypeExp())
6320 if (auto ttp = te.type.isTypeTuple())
6321 return setResult(dollarFromTypeTuple(loc, ttp, ass._scope));
6323 /* *pvar is lazily initialized, so if we refer to $
6324 * multiple times, it gets set only once.
6326 if (!*pvar) // if not already initialized
6328 /* Create variable v and set it to the value of $
6330 VarDeclaration v;
6331 Type t;
6332 if (auto tupexp = ce.isTupleExp())
6334 /* It is for an expression tuple, so the
6335 * length will be a const.
6337 Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
6338 v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
6339 v.storage_class |= STC.temp | STC.static_ | STC.const_;
6341 else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
6343 // Look for opDollar
6344 assert(exp.op == EXP.array || exp.op == EXP.slice);
6345 AggregateDeclaration ad = isAggregate(t);
6346 assert(ad);
6347 Dsymbol s = ad.search(loc, Id.opDollar);
6348 if (!s) // no dollar exists -- search in higher scope
6349 return setResult(null);
6350 s = s.toAlias();
6351 Expression e = null;
6352 // Check for multi-dimensional opDollar(dim) template.
6353 if (TemplateDeclaration td = s.isTemplateDeclaration())
6355 dinteger_t dim = 0;
6356 if (auto ae = exp.isArrayExp())
6358 dim = ae.currentDimension;
6360 else if (exp.isSliceExp())
6362 dim = 0; // slices are currently always one-dimensional
6364 else
6366 assert(0);
6368 auto tiargs = new Objects();
6369 Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
6370 edim = edim.expressionSemantic(ass._scope);
6371 tiargs.push(edim);
6372 e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
6374 else
6376 /* opDollar exists, but it's not a template.
6377 * This is acceptable ONLY for single-dimension indexing.
6378 * Note that it's impossible to have both template & function opDollar,
6379 * because both take no arguments.
6381 auto ae = exp.isArrayExp();
6382 if (ae && ae.arguments.length != 1)
6384 error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
6385 return setResult(null);
6387 Declaration d = s.isDeclaration();
6388 assert(d);
6389 e = new DotVarExp(loc, ce, d);
6391 e = e.expressionSemantic(ass._scope);
6392 if (!e.type)
6393 error(exp.loc, "`%s` has no value", e.toChars());
6394 t = e.type.toBasetype();
6395 if (t && t.ty == Tfunction)
6396 e = new CallExp(e.loc, e);
6397 v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
6398 v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
6400 else
6402 /* For arrays, $ will either be a compile-time constant
6403 * (in which case its value in set during constant-folding),
6404 * or a variable (in which case an expression is created in
6405 * toir.c).
6408 // https://issues.dlang.org/show_bug.cgi?id=16213
6409 // For static arrays $ is known at compile time,
6410 // so declare it as a manifest constant.
6411 auto tsa = ce.type ? ce.type.isTypeSArray() : null;
6412 if (tsa)
6414 auto e = new ExpInitializer(loc, tsa.dim);
6415 v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
6417 else
6419 auto e = new VoidInitializer(Loc.initial);
6420 e.type = Type.tsize_t;
6421 v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
6422 v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
6425 *pvar = v;
6427 (*pvar).dsymbolSemantic(ass._scope);
6428 return setResult((*pvar));
6432 override void visit(Import imp)
6434 //printf("%s.Import.search(ident = '%s', flags = x%x)\n", imp.toChars(), ident.toChars(), flags);
6435 if (!imp.pkg)
6437 imp.load(null);
6438 imp.mod.importAll(null);
6439 imp.mod.dsymbolSemantic(null);
6441 // Forward it to the package/module
6442 return setResult(imp.pkg.search(loc, ident, flags));
6446 override void visit(Nspace ns)
6448 //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars());
6449 if (ns._scope && !ns.symtab)
6450 dsymbolSemantic(ns, ns._scope);
6452 if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called
6454 if (!(flags & SearchOpt.ignoreErrors))
6455 .error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars());
6456 return setResult(null);
6459 visit(cast(ScopeDsymbol)ns);
6462 override void visit(EnumDeclaration em)
6464 //printf("%s.EnumDeclaration::search('%s')\n", em.toChars(), ident.toChars());
6465 if (em._scope)
6467 // Try one last time to resolve this enum
6468 dsymbolSemantic(em, em._scope);
6471 visit(cast(ScopeDsymbol)em);
6474 override void visit(Package pkg)
6476 //printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags);
6477 flags &= ~cast(int)SearchOpt.localsOnly; // searching an import is always transitive
6478 if (!pkg.isModule() && pkg.mod)
6480 // Prefer full package name.
6481 Dsymbol s = pkg.symtab ? pkg.symtab.lookup(ident) : null;
6482 if (s)
6483 return setResult(s);
6484 //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
6485 return setResult(pkg.mod.search(loc, ident, flags));
6488 visit(cast(ScopeDsymbol)pkg);
6491 override void visit(Module m)
6493 /* Since modules can be circularly referenced,
6494 * need to stop infinite recursive searches.
6495 * This is done with the cache.
6497 //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", m.toChars(), ident.toChars(), flags, m.insearch);
6498 if (m.insearch)
6499 return setResult(null);
6501 /* Qualified module searches always search their imports,
6502 * even if SearchLocalsOnly
6504 if (!(flags & SearchOpt.unqualifiedModule))
6505 flags &= ~(SearchOpt.unqualifiedModule | SearchOpt.localsOnly);
6507 if (m.searchCacheIdent == ident && m.searchCacheFlags == flags)
6509 //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
6510 // toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
6511 return setResult(m.searchCacheSymbol);
6514 uint errors = global.errors;
6516 m.insearch = true;
6517 visit(cast(ScopeDsymbol)m);
6518 Dsymbol s = result;
6519 m.insearch = false;
6521 if (errors == global.errors)
6523 // https://issues.dlang.org/show_bug.cgi?id=10752
6524 // Can cache the result only when it does not cause
6525 // access error so the side-effect should be reproduced in later search.
6526 m.searchCacheIdent = ident;
6527 m.searchCacheSymbol = s;
6528 m.searchCacheFlags = flags;
6530 return setResult(s);
6533 override void visit(Declaration decl)
6535 Dsymbol s = null;
6536 if (decl.type)
6538 s = decl.type.toDsymbol(decl._scope);
6539 if (s)
6540 s = s.search(loc, ident, flags);
6542 return setResult(s);
6545 override void visit(StructDeclaration sd)
6547 //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", sd.toChars(), ident.toChars(), flags);
6548 if (sd._scope && !sd.symtab)
6549 dsymbolSemantic(sd, sd._scope);
6551 if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called
6553 // .stringof is always defined (but may be hidden by some other symbol)
6554 if(ident != Id.stringof && !(flags & SearchOpt.ignoreErrors) && sd.semanticRun < PASS.semanticdone)
6555 .error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars());
6556 return setResult(null);
6559 visit(cast(ScopeDsymbol)sd);
6562 override void visit(ClassDeclaration cd)
6564 //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", cd.toChars(), ident.toChars(), flags);
6565 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
6566 if (cd._scope && cd.baseok < Baseok.semanticdone)
6568 if (!cd.inuse)
6570 // must semantic on base class/interfaces
6571 cd.inuse = true;
6572 dsymbolSemantic(cd, null);
6573 cd.inuse = false;
6577 if (!cd.members || !cd.symtab) // opaque or addMember is not yet done
6579 // .stringof is always defined (but may be hidden by some other symbol)
6580 if (ident != Id.stringof && !(flags & SearchOpt.ignoreErrors) && cd.semanticRun < PASS.semanticdone)
6581 cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
6582 //*(char*)0=0;
6583 return setResult(null);
6586 visit(cast(ScopeDsymbol)cd);
6587 auto s = result;
6589 // don't search imports of base classes
6590 if (flags & SearchOpt.importsOnly)
6591 return setResult(s);
6593 if (s)
6594 return setResult(s);
6596 // Search bases classes in depth-first, left to right order
6597 foreach (b; (*cd.baseclasses)[])
6599 if (!b.sym)
6600 continue;
6602 if (!b.sym.symtab)
6604 cd.classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
6605 continue;
6608 import dmd.access : symbolIsVisible;
6610 s = b.sym.search(loc, ident, flags);
6611 if (!s)
6612 continue;
6613 else if (s == cd) // happens if s is nested in this and derives from this
6614 s = null;
6615 else if (!(flags & SearchOpt.ignoreVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s))
6616 s = null;
6617 else
6618 break;
6621 return setResult(s);
6624 /*************************************
6625 * Set scope for future semantic analysis so we can
6626 * deal better with forward references.
6628 * Params:
6629 * d = dsymbol for which the scope is set
6630 * sc = scope that is used to set the value
6632 void setScope(Dsymbol d, Scope* sc)
6634 scope setScopeVisitor = new SetScopeVisitor(sc);
6635 d.accept(setScopeVisitor);
6638 private extern(C++) class SetScopeVisitor : Visitor
6640 alias visit = typeof(super).visit;
6641 Scope* sc;
6643 this(Scope* sc)
6645 this.sc = sc;
6648 override void visit(Dsymbol d)
6650 //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", d, d.toChars(), sc, sc.stc);
6651 if (!sc.nofree)
6652 sc.setNoFree(); // may need it even after semantic() finishes
6653 d._scope = sc;
6654 if (sc.depdecl)
6655 d.depdecl = sc.depdecl;
6656 if (!d.userAttribDecl)
6657 d.userAttribDecl = sc.userAttribDecl;
6660 override void visit(Import i)
6662 visit(cast(Dsymbol)i);
6663 if (i.aliasdecls.length)
6665 if (!i.mod)
6666 i.importAll(sc);
6668 sc = sc.push(i.mod);
6669 sc.visibility = i.visibility;
6670 foreach (ad; i.aliasdecls)
6671 ad.setScope(sc);
6672 sc = sc.pop();
6676 override void visit(Nspace ns)
6678 visit(cast(Dsymbol)ns);
6679 if (ns.members)
6681 assert(sc);
6682 sc = sc.push(ns);
6683 sc.linkage = LINK.cpp; // namespaces default to C++ linkage
6684 sc.parent = ns;
6685 ns.members.foreachDsymbol(s => s.setScope(sc));
6686 sc.pop();
6690 override void visit(EnumDeclaration ed)
6692 if (ed.semanticRun > PASS.initial)
6693 return;
6694 visit(cast(Dsymbol)ed);
6697 override void visit(AggregateDeclaration ad)
6699 // Might need a scope to resolve forward references. The check for
6700 // semanticRun prevents unnecessary setting of _scope during deferred
6701 // setScope phases for aggregates which already finished semantic().
6702 // See https://issues.dlang.org/show_bug.cgi?id=16607
6703 if (ad.semanticRun < PASS.semanticdone)
6704 visit(cast(Dsymbol)ad);
6707 override void visit(AttribDeclaration atr)
6709 Dsymbols* d = atr.include(sc);
6710 //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d);
6711 if (d)
6713 Scope* sc2 = atr.newScope(sc);
6714 d.foreachDsymbol( s => s.setScope(sc2) );
6715 if (sc2 != sc)
6716 sc2.pop();
6720 override void visit(DeprecatedDeclaration dd)
6722 //printf("DeprecatedDeclaration::setScope() %p\n", this);
6723 if (dd.decl)
6724 visit(cast(Dsymbol)dd); // for forward reference
6725 visit(cast(AttribDeclaration)dd);
6728 override void visit(CPPMangleDeclaration cppmd)
6730 if (cppmd.decl)
6731 visit(cast(Dsymbol)cppmd); // for forward reference
6732 visit(cast(AttribDeclaration)cppmd);
6735 override void visit(AnonDeclaration anond)
6737 if (anond.decl)
6738 visit(cast(Dsymbol)anond); // for forward reference
6739 visit(cast(AttribDeclaration)anond);
6742 override void visit(ConditionalDeclaration condd)
6744 condd.include(sc).foreachDsymbol( s => s.setScope(sc) );
6747 override void visit(StaticIfDeclaration sid)
6749 // do not evaluate condition before semantic pass
6750 // But do set the scope, in case we need it for forward referencing
6751 visit(cast(Dsymbol)sid); // for forward reference
6754 override void visit(StaticForeachDeclaration sfd)
6756 // do not evaluate condition before semantic pass
6757 // But do set the scope, in case we need it for forward referencing
6758 visit(cast(Dsymbol)sfd); // for forward reference
6761 override void visit(MixinDeclaration md)
6763 visit(cast(Dsymbol)md);
6766 override void visit(UserAttributeDeclaration uad)
6768 //printf("UserAttributeDeclaration::setScope() %p\n", this);
6769 if (uad.decl)
6770 visit(cast(Dsymbol)uad);
6771 visit(cast(AttribDeclaration)uad);
6775 void importAll(Dsymbol d, Scope* sc)
6777 scope iav = new ImportAllVisitor(sc);
6778 d.accept(iav);
6781 extern(C++) class ImportAllVisitor : Visitor
6783 alias visit = typeof(super).visit;
6784 Scope* sc;
6786 this(Scope* sc)
6788 this.sc = sc;
6791 override void visit(Dsymbol d) {}
6793 override void visit(Import imp)
6795 if (imp.mod) return; // Already done
6798 * https://issues.dlang.org/show_bug.cgi?id=15525
6800 * Loading the import has failed,
6801 * most likely because of parsing errors.
6802 * Therefore we cannot trust the resulting AST.
6804 if (imp.load(sc))
6806 // https://issues.dlang.org/show_bug.cgi?id=23873
6807 // For imports that are not at module or function level,
6808 // e.g. aggregate level, the import symbol is added to the
6809 // symbol table and later semantic is performed on it.
6810 // This leads to semantic analysis on an malformed AST
6811 // which causes all kinds of segfaults.
6812 // The fix is to note that the module has errors and avoid
6813 // semantic analysis on it.
6814 if(imp.mod)
6815 imp.mod.errors = true;
6816 return;
6819 if (!imp.mod) return; // Failed
6821 if (sc.stc & STC.static_)
6822 imp.isstatic = true;
6823 imp.mod.importAll(null);
6824 imp.mod.checkImportDeprecation(imp.loc, sc);
6825 if (sc.explicitVisibility)
6826 imp.visibility = sc.visibility;
6827 if (!imp.isstatic && !imp.aliasId && !imp.names.length)
6828 sc.scopesym.importScope(imp.mod, imp.visibility);
6829 // Enable access to pkgs/mod as soon as posible, because compiler
6830 // can traverse them before the import gets semantic (Issue: 21501)
6831 if (!imp.aliasId && !imp.names.length)
6832 imp.addPackageAccess(sc.scopesym);
6835 override void visit(Module m)
6837 //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", m, m.toChars(), m.parent);
6838 if (m._scope)
6839 return; // already done
6840 if (m.filetype == FileType.ddoc)
6842 error(m.loc, "%s `%s` is a Ddoc file, cannot import it", m.kind, m.toPrettyChars);
6843 return;
6846 /* Note that modules get their own scope, from scratch.
6847 * This is so regardless of where in the syntax a module
6848 * gets imported, it is unaffected by context.
6849 * Ignore prevsc.
6851 Scope* sc = Scope.createGlobal(m, global.errorSink); // create root scope
6853 if (m.md && m.md.msg)
6854 m.md.msg = semanticString(sc, m.md.msg, "deprecation message");
6856 // Add import of "object", even for the "object" module.
6857 // If it isn't there, some compiler rewrites, like
6858 // classinst == classinst -> .object.opEquals(classinst, classinst)
6859 // would fail inside object.d.
6860 if (m.filetype != FileType.c &&
6861 (m.members.length == 0 ||
6862 (*m.members)[0].ident != Id.object ||
6863 (*m.members)[0].isImport() is null))
6865 auto im = new Import(Loc.initial, null, Id.object, null, 0);
6866 m.members.shift(im);
6868 if (!m.symtab)
6870 // Add all symbols into module's symbol table
6871 m.symtab = new DsymbolTable();
6872 for (size_t i = 0; i < m.members.length; i++)
6874 Dsymbol s = (*m.members)[i];
6875 s.addMember(sc, sc.scopesym);
6878 // anything else should be run after addMember, so version/debug symbols are defined
6879 /* Set scope for the symbols so that if we forward reference
6880 * a symbol, it can possibly be resolved on the spot.
6881 * If this works out well, it can be extended to all modules
6882 * before any semantic() on any of them.
6884 m.setScope(sc); // remember module scope for semantic
6885 for (size_t i = 0; i < m.members.length; i++)
6887 Dsymbol s = (*m.members)[i];
6888 s.setScope(sc);
6890 for (size_t i = 0; i < m.members.length; i++)
6892 Dsymbol s = (*m.members)[i];
6893 s.importAll(sc);
6895 sc = sc.pop();
6896 sc.pop(); // 2 pops because Scope.createGlobal() created 2
6899 override void visit(AttribDeclaration atb)
6901 Dsymbols* d = atb.include(sc);
6902 //printf("\tAttribDeclaration::importAll '%s', d = %p\n", toChars(), d);
6903 if (d)
6905 Scope* sc2 = atb.newScope(sc);
6906 d.foreachDsymbol( s => s.importAll(sc2) );
6907 if (sc2 != sc)
6908 sc2.pop();
6912 // do not evaluate condition before semantic pass
6913 override void visit(StaticIfDeclaration _) {}
6914 // do not evaluate aggregate before semantic pass
6915 override void visit(StaticForeachDeclaration _) {}
6918 /*******************************
6919 * Load module.
6920 * Returns:
6921 * true for errors, false for success
6923 extern (D) bool load(Import imp, Scope* sc)
6925 // See if existing module
6926 const errors = global.errors;
6927 DsymbolTable dst = Package.resolve(imp.packages, null, &imp.pkg);
6928 version (none)
6930 if (pkg && pkg.isModule())
6932 .error(loc, "can only import from a module, not from a member of module `%s`. Did you mean `import %s : %s`?", pkg.toChars(), pkg.toPrettyChars(), id.toChars());
6933 mod = pkg.isModule(); // Error recovery - treat as import of that module
6934 return true;
6937 Dsymbol s = dst.lookup(imp.id);
6938 if (s)
6940 if (s.isModule())
6941 imp.mod = cast(Module)s;
6942 else
6944 if (s.isAliasDeclaration())
6946 .error(imp.loc, "%s `%s` conflicts with `%s`", s.kind(), s.toPrettyChars(), imp.id.toChars());
6948 else if (Package p = s.isPackage())
6950 if (p.isPkgMod == PKG.unknown)
6952 uint preverrors = global.errors;
6953 imp.mod = Module.load(imp.loc, imp.packages, imp.id);
6954 if (!imp.mod)
6955 p.isPkgMod = PKG.package_;
6956 else
6958 // imp.mod is a package.d, or a normal module which conflicts with the package name.
6959 if (imp.mod.isPackageFile)
6960 imp.mod.tag = p.tag; // reuse the same package tag
6961 else
6963 // show error if Module.load does not
6964 if (preverrors == global.errors)
6965 .error(imp.loc, "%s `%s` from file %s conflicts with %s `%s`", imp.mod.kind(), imp.mod.toPrettyChars(), imp.mod.srcfile.toChars, p.kind(), p.toPrettyChars());
6966 return true;
6970 else
6972 imp.mod = p.isPackageMod();
6974 if (!imp.mod)
6976 .error(imp.loc, "can only import from a module, not from package `%s.%s`", p.toPrettyChars(), imp.id.toChars());
6979 else if (imp.pkg)
6981 .error(imp.loc, "can only import from a module, not from package `%s.%s`", imp.pkg.toPrettyChars(), imp.id.toChars());
6983 else
6985 .error(imp.loc, "can only import from a module, not from package `%s`", imp.id.toChars());
6989 if (!imp.mod)
6991 // Load module
6992 imp.mod = Module.load(imp.loc, imp.packages, imp.id);
6993 if (imp.mod)
6995 // imp.id may be different from mod.ident, if so then insert alias
6996 dst.insert(imp.id, imp.mod);
6999 if (imp.mod && !imp.mod.importedFrom)
7000 imp.mod.importedFrom = sc ? sc._module.importedFrom : Module.rootModule;
7001 if (!imp.pkg)
7003 if (imp.mod && imp.mod.isPackageFile)
7005 // one level depth package.d file (import pkg; ./pkg/package.d)
7006 // it's necessary to use the wrapping Package already created
7007 imp.pkg = imp.mod.pkg;
7009 else
7010 imp.pkg = imp.mod;
7012 return global.errors != errors;
7015 void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion)
7017 scope v = new SetFieldOffsetVisitor(ad, fieldState, isunion);
7018 d.accept(v);
7021 private extern(C++) class SetFieldOffsetVisitor : Visitor
7023 alias visit = Visitor.visit;
7025 AggregateDeclaration ad;
7026 FieldState* fieldState;
7027 bool isunion;
7029 this(AggregateDeclaration ad, FieldState* fieldState, bool isunion)
7031 this.ad = ad;
7032 this.fieldState = fieldState;
7033 this.isunion = isunion;
7036 override void visit(Dsymbol d) {}
7038 override void visit(Nspace ns)
7040 //printf("Nspace::setFieldOffset() %s\n", toChars());
7041 if (ns._scope) // if fwd reference
7042 dsymbolSemantic(ns, null); // try to resolve it
7043 ns.members.foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
7046 override void visit(VarDeclaration vd)
7048 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), vd.toChars());
7050 if (vd.aliasTuple)
7052 // If this variable was really a tuple, set the offsets for the tuple fields
7053 vd.aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
7054 return;
7057 if (!vd.isField())
7058 return;
7059 assert(!(vd.storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
7061 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
7063 /* Fields that are tuples appear both as part of TupleDeclarations and
7064 * as members. That means ignore them if they are already a field.
7066 if (vd.offset)
7068 // already a field
7069 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
7070 return;
7072 for (size_t i = 0; i < ad.fields.length; i++)
7074 if (ad.fields[i] == vd)
7076 // already a field
7077 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
7078 return;
7082 // Check for forward referenced types which will fail the size() call
7083 Type t = vd.type.toBasetype();
7084 if (vd.storage_class & STC.ref_)
7086 // References are the size of a pointer
7087 t = Type.tvoidptr;
7089 Type tv = t.baseElemOf();
7090 if (tv.ty == Tstruct)
7092 auto ts = cast(TypeStruct)tv;
7093 assert(ts.sym != ad); // already checked in ad.determineFields()
7094 if (!ts.sym.determineSize(vd.loc))
7096 vd.type = Type.terror;
7097 vd.errors = true;
7098 return;
7102 // List in ad.fields. Even if the type is error, it's necessary to avoid
7103 // pointless error diagnostic "more initializers than fields" on struct literal.
7104 ad.fields.push(vd);
7106 if (t.ty == Terror)
7107 return;
7109 /* If coming after a bit field in progress,
7110 * advance past the field
7112 fieldState.inFlight = false;
7114 const sz = t.size(vd.loc);
7115 assert(sz != SIZE_INVALID && sz < uint.max);
7116 uint memsize = cast(uint)sz; // size of member
7117 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
7118 vd.offset = placeField(
7119 fieldState.offset,
7120 memsize, memalignsize, vd.alignment,
7121 ad.structsize, ad.alignsize,
7122 isunion);
7124 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
7125 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
7128 override void visit(BitFieldDeclaration bfd)
7130 enum log = false;
7131 static if (log)
7133 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), bfd.toChars());
7134 void print(const FieldState* fieldState)
7136 fieldState.print();
7137 printf(" fieldWidth = %d bits\n", bfd.fieldWidth);
7139 print(fieldState);
7142 Type t = bfd.type.toBasetype();
7143 const bool anon = bfd.isAnonymous();
7145 // List in ad.fields. Even if the type is error, it's necessary to avoid
7146 // pointless error diagnostic "more initializers than fields" on struct literal.
7147 if (!anon)
7148 ad.fields.push(bfd);
7150 if (t.ty == Terror)
7151 return;
7153 const sz = t.size(bfd.loc);
7154 assert(sz != SIZE_INVALID && sz < uint.max);
7155 uint memsize = cast(uint)sz; // size of member
7156 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
7157 if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
7159 if (bfd.fieldWidth == 0 && !anon)
7160 error(bfd.loc, "named bit fields cannot have 0 width");
7161 if (bfd.fieldWidth > memsize * 8)
7162 error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth);
7164 const style = target.c.bitFieldStyle;
7166 void startNewField()
7168 if (log) printf("startNewField()\n");
7169 uint alignsize;
7170 if (style == TargetC.BitFieldStyle.Gcc_Clang)
7172 if (bfd.fieldWidth > 32)
7173 alignsize = memalignsize;
7174 else if (bfd.fieldWidth > 16)
7175 alignsize = 4;
7176 else if (bfd.fieldWidth > 8)
7177 alignsize = 2;
7178 else
7179 alignsize = 1;
7181 else
7182 alignsize = memsize; // not memalignsize
7184 uint dummy;
7185 bfd.offset = placeField(
7186 fieldState.offset,
7187 memsize, alignsize, bfd.alignment,
7188 ad.structsize,
7189 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? dummy : ad.alignsize,
7190 isunion);
7192 fieldState.inFlight = true;
7193 fieldState.fieldOffset = bfd.offset;
7194 fieldState.bitOffset = 0;
7195 fieldState.fieldSize = memsize;
7198 if (style == TargetC.BitFieldStyle.Gcc_Clang)
7200 if (bfd.fieldWidth == 0)
7202 if (!isunion)
7204 // Use type of zero width field to align to next field
7205 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
7206 ad.structsize = fieldState.offset;
7209 fieldState.inFlight = false;
7210 return;
7213 if (ad.alignsize == 0)
7214 ad.alignsize = 1;
7215 if (!anon &&
7216 ad.alignsize < memalignsize)
7217 ad.alignsize = memalignsize;
7219 else if (style == TargetC.BitFieldStyle.MS)
7221 if (ad.alignsize == 0)
7222 ad.alignsize = 1;
7223 if (bfd.fieldWidth == 0)
7225 if (fieldState.inFlight && !isunion)
7227 // documentation says align to next int
7228 //const alsz = cast(uint)Type.tint32.size();
7229 const alsz = memsize; // but it really does this
7230 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
7231 ad.structsize = fieldState.offset;
7234 fieldState.inFlight = false;
7235 return;
7238 else if (style == TargetC.BitFieldStyle.DM)
7240 if (anon && bfd.fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
7241 return; // this probably should be a bug in DMC
7242 if (ad.alignsize == 0)
7243 ad.alignsize = 1;
7244 if (bfd.fieldWidth == 0)
7246 if (fieldState.inFlight && !isunion)
7248 const alsz = memsize;
7249 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
7250 ad.structsize = fieldState.offset;
7253 fieldState.inFlight = false;
7254 return;
7258 if (!fieldState.inFlight)
7260 //printf("not in flight\n");
7261 startNewField();
7263 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
7265 // If the bit-field spans more units of alignment than its type,
7266 // start a new field at the next alignment boundary.
7267 if (fieldState.bitOffset == fieldState.fieldSize * 8 &&
7268 fieldState.bitOffset + bfd.fieldWidth > memalignsize * 8)
7270 if (log) printf("more units of alignment than its type\n");
7271 startNewField(); // the bit field is full
7273 else
7275 // if alignment boundary is crossed
7276 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
7277 uint end = start + bfd.fieldWidth;
7278 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
7279 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
7281 if (log) printf("alignment is crossed\n");
7282 startNewField();
7286 else if (style == TargetC.BitFieldStyle.DM ||
7287 style == TargetC.BitFieldStyle.MS)
7289 if (memsize != fieldState.fieldSize ||
7290 fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8)
7292 //printf("new field\n");
7293 startNewField();
7296 else
7297 assert(0);
7299 bfd.offset = fieldState.fieldOffset;
7300 bfd.bitOffset = fieldState.bitOffset;
7302 const pastField = bfd.bitOffset + bfd.fieldWidth;
7303 if (style == TargetC.BitFieldStyle.Gcc_Clang)
7305 auto size = (pastField + 7) / 8;
7306 fieldState.fieldSize = size;
7307 //printf(" offset: %d, size: %d\n", offset, size);
7308 if (isunion)
7310 const newstructsize = bfd.offset + size;
7311 if (newstructsize > ad.structsize)
7312 ad.structsize = newstructsize;
7314 else
7315 ad.structsize = bfd.offset + size;
7317 else
7318 fieldState.fieldSize = memsize;
7319 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
7320 //print(fieldState);
7322 if (!isunion)
7324 fieldState.offset = bfd.offset + fieldState.fieldSize;
7325 fieldState.bitOffset = pastField;
7328 //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
7329 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
7330 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
7333 override void visit(TemplateMixin tm)
7335 //printf("TemplateMixin.setFieldOffset() %s\n", tm.toChars());
7336 if (tm._scope) // if fwd reference
7337 dsymbolSemantic(tm, null); // try to resolve it
7339 tm.members.foreachDsymbol( (s) { s.setFieldOffset(ad, fieldState, isunion); } );
7342 override void visit(AttribDeclaration atd)
7344 atd.include(null).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
7347 override void visit(AnonDeclaration anond)
7349 //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", anond);
7350 if (anond.decl)
7352 /* This works by treating an AnonDeclaration as an aggregate 'member',
7353 * so in order to place that member we need to compute the member's
7354 * size and alignment.
7356 size_t fieldstart = ad.fields.length;
7358 /* Hackishly hijack ad's structsize and alignsize fields
7359 * for use in our fake anon aggregate member.
7361 uint savestructsize = ad.structsize;
7362 uint savealignsize = ad.alignsize;
7363 ad.structsize = 0;
7364 ad.alignsize = 0;
7366 FieldState fs;
7367 anond.decl.foreachDsymbol( (s)
7369 s.setFieldOffset(ad, &fs, anond.isunion);
7370 if (anond.isunion)
7371 fs.offset = 0;
7374 /* https://issues.dlang.org/show_bug.cgi?id=13613
7375 * If the fields in this.members had been already
7376 * added in ad.fields, just update *poffset for the subsequent
7377 * field offset calculation.
7379 if (fieldstart == ad.fields.length)
7381 ad.structsize = savestructsize;
7382 ad.alignsize = savealignsize;
7383 fieldState.offset = ad.structsize;
7384 return;
7387 anond.anonstructsize = ad.structsize;
7388 anond.anonalignsize = ad.alignsize;
7389 ad.structsize = savestructsize;
7390 ad.alignsize = savealignsize;
7392 // 0 sized structs are set to 1 byte
7393 if (anond.anonstructsize == 0)
7395 anond.anonstructsize = 1;
7396 anond.anonalignsize = 1;
7399 assert(anond._scope);
7400 auto alignment = anond._scope.alignment();
7402 /* Given the anon 'member's size and alignment,
7403 * go ahead and place it.
7405 anond.anonoffset = placeField(
7406 fieldState.offset,
7407 anond.anonstructsize, anond.anonalignsize, alignment,
7408 ad.structsize, ad.alignsize,
7409 isunion);
7411 // Add to the anon fields the base offset of this anonymous aggregate
7412 //printf("anon fields, anonoffset = %d\n", anonoffset);
7413 foreach (const i; fieldstart .. ad.fields.length)
7415 VarDeclaration v = ad.fields[i];
7416 //printf("\t[%d] %s %d\n", i, v.toChars(), v.offset);
7417 v.offset += anond.anonoffset;