d: Merge dmd. druntime e770945277, phobos 6d6e0b9b9
[official-gcc.git] / gcc / d / dmd / dsymbolsem.d
blob658beafdf839c148b951ec7305a9f76e5c24ad6f
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.blockexit;
25 import dmd.clone;
26 import dmd.cond;
27 import dmd.compiler;
28 import dmd.dcast;
29 import dmd.dclass;
30 import dmd.declaration;
31 import dmd.denum;
32 import dmd.dimport;
33 import dmd.dinterpret;
34 import dmd.dmangle;
35 import dmd.dmodule;
36 import dmd.dscope;
37 import dmd.dstruct;
38 import dmd.dsymbol;
39 import dmd.dtemplate;
40 import dmd.dversion;
41 import dmd.enumsem;
42 import dmd.errors;
43 import dmd.escape;
44 import dmd.expression;
45 import dmd.expressionsem;
46 import dmd.func;
47 import dmd.funcsem;
48 import dmd.globals;
49 import dmd.id;
50 import dmd.identifier;
51 import dmd.importc;
52 import dmd.init;
53 import dmd.initsem;
54 import dmd.intrange;
55 import dmd.hdrgen;
56 import dmd.location;
57 import dmd.mtype;
58 import dmd.mustuse;
59 import dmd.nogc;
60 import dmd.nspace;
61 import dmd.objc;
62 import dmd.opover;
63 import dmd.optimize;
64 import dmd.parse;
65 import dmd.root.array;
66 import dmd.root.filename;
67 import dmd.common.outbuffer;
68 import dmd.root.rmem;
69 import dmd.rootobject;
70 import dmd.root.utf;
71 import dmd.semantic2;
72 import dmd.semantic3;
73 import dmd.sideeffect;
74 import dmd.statementsem;
75 import dmd.staticassert;
76 import dmd.tokens;
77 import dmd.utils;
78 import dmd.statement;
79 import dmd.target;
80 import dmd.templateparamsem;
81 import dmd.typesem;
82 import dmd.visitor;
84 version (IN_GCC) {}
85 else version (IN_LLVM) {}
86 else version = MARS;
88 enum LOG = false;
90 package uint setMangleOverride(Dsymbol s, const(char)[] sym)
92 if (s.isFuncDeclaration() || s.isVarDeclaration())
94 s.isDeclaration().mangleOverride = sym;
95 return 1;
98 if (auto ad = s.isAttribDeclaration())
100 uint nestedCount = 0;
102 ad.include(null).foreachDsymbol( (s) { nestedCount += setMangleOverride(s, sym); } );
104 return nestedCount;
106 return 0;
110 * Apply pragma printf/scanf to FuncDeclarations under `s`,
111 * poking through attribute declarations such as `extern(C)`
112 * but not through aggregates or function bodies.
114 * Params:
115 * s = symbol to apply
116 * printf = `true` for printf, `false` for scanf
118 private void setPragmaPrintf(Dsymbol s, bool printf)
120 if (auto fd = s.isFuncDeclaration())
122 fd.printf = printf;
123 fd.scanf = !printf;
126 if (auto ad = s.isAttribDeclaration())
128 ad.include(null).foreachDsymbol( (s) { setPragmaPrintf(s, printf); } );
132 /*************************************
133 * Does semantic analysis on the public face of declarations.
135 extern(C++) void dsymbolSemantic(Dsymbol dsym, Scope* sc)
137 scope v = new DsymbolSemanticVisitor(sc);
138 dsym.accept(v);
141 /***************************************************
142 * Determine the numerical value of the AlignmentDeclaration
143 * Params:
144 * ad = AlignmentDeclaration
145 * sc = context
146 * Returns:
147 * ad with alignment value determined
149 AlignDeclaration getAlignment(AlignDeclaration ad, Scope* sc)
151 if (!ad.salign.isUnknown()) // UNKNOWN is 0
152 return ad;
154 if (!ad.exps)
156 ad.salign.setDefault();
157 return ad;
160 dinteger_t strictest = 0; // strictest alignment
161 bool errors;
162 foreach (ref exp; (*ad.exps)[])
164 sc = sc.startCTFE();
165 auto e = exp.expressionSemantic(sc);
166 e = resolveProperties(sc, e);
167 sc = sc.endCTFE();
168 e = e.ctfeInterpret();
169 exp = e; // could be re-evaluated if exps are assigned to more than one AlignDeclaration by CParser.applySpecifier(),
170 // e.g. `_Alignas(8) int a, b;`
171 if (e.op == EXP.error)
172 errors = true;
173 else
175 auto n = e.toInteger();
176 if (sc.flags & SCOPE.Cfile && n == 0) // C11 6.7.5-6 allows 0 for alignment
177 continue;
179 if (n < 1 || n & (n - 1) || ushort.max < n || !e.type.isintegral())
181 error(ad.loc, "alignment must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
182 errors = true;
184 if (n > strictest) // C11 6.7.5-6
185 strictest = n;
189 if (errors || strictest == 0) // C11 6.7.5-6 says alignment of 0 means no effect
190 ad.salign.setDefault();
191 else
192 ad.salign.set(cast(uint) strictest);
194 return ad;
197 const(char)* getMessage(DeprecatedDeclaration dd)
199 if (auto sc = dd._scope)
201 dd._scope = null;
203 sc = sc.startCTFE();
204 dd.msg = dd.msg.expressionSemantic(sc);
205 dd.msg = resolveProperties(sc, dd.msg);
206 sc = sc.endCTFE();
207 dd.msg = dd.msg.ctfeInterpret();
209 if (auto se = dd.msg.toStringExp())
210 dd.msgstr = se.toStringz().ptr;
211 else
212 error(dd.msg.loc, "compile time constant expected, not `%s`", dd.msg.toChars());
214 return dd.msgstr;
217 bool checkDeprecated(Dsymbol d, const ref Loc loc, Scope* sc)
219 if (global.params.useDeprecated == DiagnosticReporting.off)
220 return false;
221 if (!d.isDeprecated())
222 return false;
223 // Don't complain if we're inside a deprecated symbol's scope
224 if (sc.isDeprecated())
225 return false;
226 // Don't complain if we're inside a template constraint
227 // https://issues.dlang.org/show_bug.cgi?id=21831
228 if (sc.flags & SCOPE.constraint)
229 return false;
231 const(char)* message = null;
232 for (Dsymbol p = d; p; p = p.parent)
234 message = p.depdecl ? p.depdecl.getMessage() : null;
235 if (message)
236 break;
238 if (message)
239 deprecation(loc, "%s `%s` is deprecated - %s", d.kind, d.toPrettyChars, message);
240 else
241 deprecation(loc, "%s `%s` is deprecated", d.kind, d.toPrettyChars);
243 if (auto ti = sc.parent ? sc.parent.isInstantiated() : null)
244 ti.printInstantiationTrace(Classification.deprecation);
245 else if (auto ti = sc.parent ? sc.parent.isTemplateInstance() : null)
246 ti.printInstantiationTrace(Classification.deprecation);
248 return true;
251 /*********************************
252 * Check type to see if it is based on a deprecated symbol.
254 private void checkDeprecated(Type type, const ref Loc loc, Scope* sc)
256 if (Dsymbol s = type.toDsymbol(sc))
258 s.checkDeprecated(loc, sc);
261 if (auto tn = type.nextOf())
262 tn.checkDeprecated(loc, sc);
265 // Returns true if a contract can appear without a function body.
266 package bool allowsContractWithoutBody(FuncDeclaration funcdecl)
268 assert(!funcdecl.fbody);
270 /* Contracts can only appear without a body when they are virtual
271 * interface functions or abstract.
273 Dsymbol parent = funcdecl.toParent();
274 InterfaceDeclaration id = parent.isInterfaceDeclaration();
276 if (!funcdecl.isAbstract() &&
277 (funcdecl.fensures || funcdecl.frequires) &&
278 !(id && funcdecl.isVirtual()))
280 auto cd = parent.isClassDeclaration();
281 if (!(cd && cd.isAbstract()))
282 return false;
284 return true;
288 Tests whether the `ctor` that is part of `ti` is an rvalue constructor
289 (i.e. a constructor that receives a single parameter of the same type as
290 `Unqual!typeof(this)`). If that is the case and `sd` contains a copy
291 constructor, than an error is issued.
293 Params:
294 sd = struct declaration that may contin both an rvalue and copy constructor
295 ctor = constructor that will be checked if it is an evalue constructor
296 ti = template instance the ctor is part of
298 Return:
299 `false` if ctor is not an rvalue constructor or if `sd` does not contain a
300 copy constructor. `true` otherwise
302 bool checkHasBothRvalueAndCpCtor(StructDeclaration sd, CtorDeclaration ctor, TemplateInstance ti)
304 auto loc = ctor.loc;
305 auto tf = cast(TypeFunction)ctor.type;
306 auto dim = tf.parameterList.length;
307 if (sd && sd.hasCopyCtor && (dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
309 auto param = tf.parameterList[0];
310 if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
312 .error(loc, "cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars());
313 .errorSupplemental(ti.loc, "Template instance `%s` creates an rvalue constructor for `struct %s`",
314 ti.toPrettyChars(), sd.toChars());
316 return true;
320 return false;
323 /*************************************
324 * Find the `alias this` symbol of e's type.
325 * Params:
326 * sc = context
327 * e = expression forming the `this`
328 * gag = do not print errors, return `null` instead
329 * findOnly = don't do further processing like resolving properties,
330 * i.e. just return plain dotExp() result.
331 * Returns:
332 * Expression that is `e.aliasthis`
334 Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool findOnly = false)
336 import dmd.typesem : dotExp;
337 for (AggregateDeclaration ad = isAggregate(e.type); ad;)
339 if (ad.aliasthis)
341 Loc loc = e.loc;
342 Type tthis = (e.op == EXP.type ? e.type : null);
343 const flags = cast(DotExpFlag) (DotExpFlag.noAliasThis | (gag * DotExpFlag.gag));
344 uint olderrors = gag ? global.startGagging() : 0;
345 e = dotExp(ad.type, sc, e, ad.aliasthis.ident, flags);
346 if (!e || findOnly)
347 return gag && global.endGagging(olderrors) ? null : e;
349 if (tthis && ad.aliasthis.sym.needThis())
351 if (auto ve = e.isVarExp())
353 if (auto fd = ve.var.isFuncDeclaration())
355 // https://issues.dlang.org/show_bug.cgi?id=13009
356 // Support better match for the overloaded alias this.
357 bool hasOverloads;
358 if (auto f = fd.overloadModMatch(loc, tthis, hasOverloads))
360 if (!hasOverloads)
361 fd = f; // use exact match
362 e = new VarExp(loc, fd, hasOverloads);
363 e.type = f.type;
364 e = new CallExp(loc, e);
365 goto L1;
369 /* non-@property function is not called inside typeof(),
370 * so resolve it ahead.
373 int save = sc.intypeof;
374 sc.intypeof = 1; // bypass "need this" error check
375 e = resolveProperties(sc, e);
376 sc.intypeof = save;
379 e = new TypeExp(loc, new TypeTypeof(loc, e));
380 e = e.expressionSemantic(sc);
382 e = resolveProperties(sc, e);
383 if (!gag)
384 ad.aliasthis.checkDeprecatedAliasThis(loc, sc);
385 else if (global.endGagging(olderrors))
386 e = null;
389 import dmd.dclass : ClassDeclaration;
390 auto cd = ad.isClassDeclaration();
391 if ((!e || !ad.aliasthis) && cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
393 ad = cd.baseClass;
394 continue;
396 break;
398 return e;
402 * Check if an `alias this` is deprecated
404 * Usually one would use `expression.checkDeprecated(scope, aliasthis)` to
405 * check if `expression` uses a deprecated `aliasthis`, but this calls
406 * `toPrettyChars` which lead to the following message:
407 * "Deprecation: alias this `fullyqualified.aggregate.__anonymous` is deprecated"
409 * Params:
410 * at = The `AliasThis` object to check
411 * loc = `Loc` of the expression triggering the access to `at`
412 * sc = `Scope` of the expression
413 * (deprecations do not trigger in deprecated scopes)
415 * Returns:
416 * Whether the alias this was reported as deprecated.
418 private bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc)
420 if (global.params.useDeprecated != DiagnosticReporting.off
421 && at.isDeprecated() && !sc.isDeprecated())
423 const(char)* message = null;
424 for (Dsymbol p = at; p; p = p.parent)
426 message = p.depdecl ? p.depdecl.getMessage() : null;
427 if (message)
428 break;
430 if (message)
431 deprecation(loc, "`alias %s this` is deprecated - %s",
432 at.sym.toChars(), message);
433 else
434 deprecation(loc, "`alias %s this` is deprecated",
435 at.sym.toChars());
437 if (auto ti = sc.parent ? sc.parent.isInstantiated() : null)
438 ti.printInstantiationTrace(Classification.deprecation);
440 return true;
442 return false;
445 // Save the scope and defer semantic analysis on the Dsymbol.
446 void deferDsymbolSemantic(Scope* sc, Dsymbol s, Scope *scx)
448 s._scope = scx ? scx : sc.copy();
449 s._scope.setNoFree();
450 Module.addDeferredSemantic(s);
454 private extern(C++) final class DsymbolSemanticVisitor : Visitor
456 alias visit = Visitor.visit;
458 Scope* sc;
459 this(Scope* sc) scope @safe
461 this.sc = sc;
464 override void visit(Dsymbol dsym)
466 .error(dsym.loc, "%s `%s` %p has no semantic routine", dsym.kind, dsym.toPrettyChars, dsym);
469 override void visit(ScopeDsymbol) { }
470 override void visit(Declaration) { }
472 override void visit(AliasThis dsym)
474 if (dsym.semanticRun != PASS.initial)
475 return;
477 if (dsym._scope)
479 sc = dsym._scope;
480 dsym._scope = null;
483 if (!sc)
484 return;
486 dsym.semanticRun = PASS.semantic;
487 dsym.isDeprecated_ = !!(sc.stc & STC.deprecated_);
489 Dsymbol p = sc.parent.pastMixin();
490 AggregateDeclaration ad = p.isAggregateDeclaration();
491 if (!ad)
493 error(dsym.loc, "alias this can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
494 return;
497 assert(ad.members);
498 Dsymbol s = ad.search(dsym.loc, dsym.ident);
499 if (!s)
501 Dsymbol pscopesym;
502 s = sc.search(dsym.loc, dsym.ident, pscopesym);
503 if (s)
504 error(dsym.loc, "`%s` is not a member of `%s`", s.toChars(), ad.toChars());
505 else
506 error(dsym.loc, "undefined identifier `%s`", dsym.ident.toChars());
507 return;
509 if (ad.aliasthis && s != ad.aliasthis)
511 error(dsym.loc, "there can be only one alias this");
512 return;
515 /* disable the alias this conversion so the implicit conversion check
516 * doesn't use it.
518 ad.aliasthis = null;
520 Dsymbol sx = s;
521 if (sx.isAliasDeclaration())
522 sx = sx.toAlias();
523 Declaration d = sx.isDeclaration();
524 if (d && !d.isTupleDeclaration())
526 /* https://issues.dlang.org/show_bug.cgi?id=18429
528 * If the identifier in the AliasThis declaration
529 * is defined later and is a voldemort type, we must
530 * perform semantic on the declaration to deduce the type.
532 if (!d.type)
533 d.dsymbolSemantic(sc);
535 Type t = d.type;
536 assert(t);
537 if (ad.type.implicitConvTo(t) > MATCH.nomatch)
539 error(dsym.loc, "alias this is not reachable as `%s` already converts to `%s`", ad.toChars(), t.toChars());
543 dsym.sym = s;
544 // Restore alias this
545 ad.aliasthis = dsym;
546 dsym.semanticRun = PASS.semanticdone;
549 override void visit(AliasDeclaration dsym)
551 if (dsym.semanticRun >= PASS.semanticdone)
552 return;
553 assert(dsym.semanticRun <= PASS.semantic);
555 if (!sc)
556 return;
558 dsym.semanticRun = PASS.semantic;
560 dsym.storage_class |= sc.stc & STC.deprecated_;
561 dsym.visibility = sc.visibility;
562 dsym.userAttribDecl = sc.userAttribDecl;
564 if (!sc.func && dsym.inNonRoot())
565 return;
567 aliasSemantic(dsym, sc);
570 override void visit(AliasAssign dsym)
572 //printf("visit(AliasAssign)\n");
573 if (dsym.semanticRun >= PASS.semanticdone)
574 return;
575 assert(dsym.semanticRun <= PASS.semantic);
577 if (!sc.func && dsym.inNonRoot())
578 return;
580 aliasAssignSemantic(dsym, sc);
583 override void visit(VarDeclaration dsym)
585 version (none)
587 printf("VarDeclaration::semantic('%s', parent = '%s') sem = %d\n",
588 dsym.toChars(), sc.parent ? sc.parent.toChars() : null, dsym.semanticRun);
589 printf(" type = %s\n", dsym.type ? dsym.type.toChars() : "null");
590 printf(" stc = x%llx\n", dsym.storage_class);
591 printf(" storage_class = x%llx\n", dsym.storage_class);
592 printf("linkage = %d\n", dsym._linkage);
593 //if (strcmp(toChars(), "mul") == 0) assert(0);
595 //if (semanticRun > PASS.initial)
596 // return;
597 //semanticRun = PSSsemantic;
599 if (dsym.semanticRun >= PASS.semanticdone)
600 return;
602 if (sc && sc.inunion && sc.inunion.isAnonDeclaration())
603 dsym.overlapped = true;
605 dsym.sequenceNumber = global.varSequenceNumber++;
606 if (!dsym.isScope())
607 dsym.maybeScope = true;
609 Scope* scx = null;
610 if (dsym._scope)
612 sc = dsym._scope;
613 scx = sc;
614 dsym._scope = null;
617 if (!sc)
618 return;
620 dsym.semanticRun = PASS.semantic;
622 // 'static foreach' variables should not inherit scope properties
623 // https://issues.dlang.org/show_bug.cgi?id=19482
624 if ((dsym.storage_class & (STC.foreach_ | STC.local)) == (STC.foreach_ | STC.local))
626 dsym._linkage = LINK.d;
627 dsym.visibility = Visibility(Visibility.Kind.public_);
628 dsym.overlapped = false; // unset because it is modified early on this function
629 dsym.userAttribDecl = null; // unset because it is set by Dsymbol.setScope()
631 else
633 /* Pick up storage classes from context, but except synchronized,
634 * override, abstract, and final.
636 dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
637 dsym.userAttribDecl = sc.userAttribDecl;
638 dsym.cppnamespace = sc.namespace;
639 dsym._linkage = sc.linkage;
640 dsym.visibility = sc.visibility;
641 dsym.alignment = sc.alignment();
644 if (dsym.storage_class & STC.extern_ && dsym._init)
645 .error(dsym.loc, "%s `%s` extern symbols cannot have initializers", dsym.kind, dsym.toPrettyChars);
647 AggregateDeclaration ad = dsym.isThis();
648 if (ad)
649 dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
651 /* If auto type inference, do the inference
653 int inferred = 0;
654 if (!dsym.type)
656 dsym.inuse++;
658 // Infering the type requires running semantic,
659 // so mark the scope as ctfe if required
660 bool needctfe = (dsym.storage_class & (STC.manifest | STC.static_)) != 0 || !sc.func;
661 if (needctfe)
663 sc.flags |= SCOPE.condition;
664 sc = sc.startCTFE();
666 //printf("inferring type for %s with init %s\n", dsym.toChars(), dsym._init.toChars());
667 dsym._init = dsym._init.inferType(sc);
668 dsym.type = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0).type;
669 if (needctfe)
670 sc = sc.endCTFE();
672 dsym.inuse--;
673 inferred = 1;
675 /* This is a kludge to support the existing syntax for RAII
676 * declarations.
678 dsym.storage_class &= ~STC.auto_;
679 dsym.originalType = dsym.type.syntaxCopy();
681 else
683 if (!dsym.originalType)
684 dsym.originalType = dsym.type.syntaxCopy();
686 /* Prefix function attributes of variable declaration can affect
687 * its type:
688 * pure nothrow void function() fp;
689 * static assert(is(typeof(fp) == void function() pure nothrow));
691 Scope* sc2 = sc.push();
692 sc2.stc |= (dsym.storage_class & STC.FUNCATTR);
693 dsym.inuse++;
694 dsym.type = dsym.type.typeSemantic(dsym.loc, sc2);
695 dsym.inuse--;
696 sc2.pop();
698 //printf(" semantic type = %s\n", dsym.type ? dsym.type.toChars() : "null");
699 if (dsym.type.ty == Terror)
700 dsym.errors = true;
702 dsym.type.checkDeprecated(dsym.loc, sc);
703 dsym.parent = sc.parent;
704 //printf("this = %p, parent = %p, '%s'\n", dsym, dsym.parent, dsym.parent.toChars());
706 /* If scope's alignment is the default, use the type's alignment,
707 * otherwise the scope overrrides.
709 if (dsym.alignment.isDefault())
710 dsym.alignment = dsym.type.alignment(); // use type's alignment
712 //printf("sc.stc = %x\n", sc.stc);
713 //printf("storage_class = x%x\n", storage_class);
715 dsym.type.checkComplexTransition(dsym.loc, sc);
717 // Calculate type size + safety checks
718 if (dsym.storage_class & STC.gshared && !dsym.isMember())
720 sc.setUnsafe(false, dsym.loc, "__gshared not allowed in safe functions; use shared");
723 Dsymbol parent = dsym.toParent();
725 Type tb = dsym.type.toBasetype();
726 Type tbn = tb.baseElemOf();
727 if (tb.ty == Tvoid && !(dsym.storage_class & STC.lazy_))
729 if (inferred)
731 .error(dsym.loc, "%s `%s` - type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`",
732 dsym.kind, dsym.toPrettyChars, dsym.type.toChars(), toChars(dsym._init));
734 else
735 .error(dsym.loc, "%s `%s` - variables cannot be of type `void`", dsym.kind, dsym.toPrettyChars);
736 dsym.type = Type.terror;
737 tb = dsym.type;
739 if (tb.ty == Tfunction)
741 .error(dsym.loc, "%s `%s` cannot be declared to be a function", dsym.kind, dsym.toPrettyChars);
742 dsym.type = Type.terror;
743 tb = dsym.type;
745 if (auto ts = tb.isTypeStruct())
747 // Require declarations, except when it's just a reference (as done for pointers)
748 // or when the variable is defined externally
749 if (!ts.sym.members && !(dsym.storage_class & (STC.ref_ | STC.extern_)))
751 .error(dsym.loc, "%s `%s` - no definition of struct `%s`", dsym.kind, dsym.toPrettyChars, ts.toChars());
753 // Explain why the definition is required when it's part of another type
754 if (!dsym.type.isTypeStruct())
756 // Prefer Loc of the dependant type
757 const s = dsym.type.toDsymbol(sc);
758 const loc = (s ? s : dsym).loc;
759 loc.errorSupplemental("required by type `%s`", dsym.type.toChars());
761 errorSupplemental(dsym.loc, "see https://dlang.org/spec/struct.html#opaque_struct_unions");
762 errorSupplemental(dsym.loc, "perhaps declare a variable with pointer type `%s*` instead", dsym.type.toChars());
764 // Flag variable as error to avoid invalid error messages due to unknown size
765 dsym.type = Type.terror;
768 if ((dsym.storage_class & STC.auto_) && !inferred)
769 .error(dsym.loc, "%s `%s` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?", dsym.kind, dsym.toPrettyChars);
771 if (auto tt = tb.isTypeTuple())
773 /* Instead, declare variables for each of the tuple elements
774 * and add those.
776 size_t nelems = Parameter.dim(tt.arguments);
777 Expression ie = (dsym._init && !dsym._init.isVoidInitializer()) ? dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0) : null;
778 if (ie)
779 ie = ie.expressionSemantic(sc);
780 if (nelems > 0 && ie)
782 auto iexps = new Expressions();
783 iexps.push(ie);
784 auto exps = new Expressions();
785 for (size_t pos = 0; pos < iexps.length; pos++)
787 Lexpand1:
788 Expression e = (*iexps)[pos];
789 Parameter arg = Parameter.getNth(tt.arguments, pos);
790 arg.type = arg.type.typeSemantic(dsym.loc, sc);
791 //printf("[%d] iexps.length = %d, ", pos, iexps.length);
792 //printf("e = (%s %s, %s), ", Token.tochars[e.op], e.toChars(), e.type.toChars());
793 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
795 if (e != ie)
797 if (iexps.length > nelems)
798 goto Lnomatch;
799 if (e.type.implicitConvTo(arg.type))
800 continue;
803 if (auto te = e.isTupleExp())
805 if (iexps.length - 1 + te.exps.length > nelems)
806 goto Lnomatch;
808 iexps.remove(pos);
809 iexps.insert(pos, te.exps);
810 (*iexps)[pos] = Expression.combine(te.e0, (*iexps)[pos]);
811 goto Lexpand1;
813 else if (isAliasThisTuple(e))
815 auto v = copyToTemp(0, "__tup", e);
816 v.dsymbolSemantic(sc);
817 auto ve = new VarExp(dsym.loc, v);
818 ve.type = e.type;
820 exps.setDim(1);
821 (*exps)[0] = ve;
822 expandAliasThisTuples(exps, 0);
824 for (size_t u = 0; u < exps.length; u++)
826 Lexpand2:
827 Expression ee = (*exps)[u];
828 arg = Parameter.getNth(tt.arguments, pos + u);
829 arg.type = arg.type.typeSemantic(dsym.loc, sc);
830 //printf("[%d+%d] exps.length = %d, ", pos, u, exps.length);
831 //printf("ee = (%s %s, %s), ", Token.tochars[ee.op], ee.toChars(), ee.type.toChars());
832 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
834 size_t iexps_dim = iexps.length - 1 + exps.length;
835 if (iexps_dim > nelems)
836 goto Lnomatch;
837 if (ee.type.implicitConvTo(arg.type))
838 continue;
840 if (expandAliasThisTuples(exps, u) != -1)
841 goto Lexpand2;
844 if ((*exps)[0] != ve)
846 Expression e0 = (*exps)[0];
847 (*exps)[0] = new CommaExp(dsym.loc, new DeclarationExp(dsym.loc, v), e0);
848 (*exps)[0].type = e0.type;
850 iexps.remove(pos);
851 iexps.insert(pos, exps);
852 goto Lexpand1;
856 if (iexps.length < nelems)
857 goto Lnomatch;
859 ie = new TupleExp(dsym._init.loc, iexps);
861 Lnomatch:
863 if (ie && ie.op == EXP.tuple)
865 auto te = ie.isTupleExp();
866 size_t tedim = te.exps.length;
867 if (tedim != nelems)
869 error(dsym.loc, "sequence of %d elements cannot be assigned to sequence of %d elements", cast(int)tedim, cast(int)nelems);
870 for (size_t u = tedim; u < nelems; u++) // fill dummy expression
871 te.exps.push(ErrorExp.get());
875 auto exps = new Objects(nelems);
876 for (size_t i = 0; i < nelems; i++)
878 Parameter arg = Parameter.getNth(tt.arguments, i);
880 OutBuffer buf;
881 buf.printf("__%s_field_%llu", dsym.ident.toChars(), cast(ulong)i);
882 auto id = Identifier.idPool(buf[]);
884 Initializer ti;
885 if (ie)
887 Expression einit = ie;
888 if (auto te = ie.isTupleExp())
890 einit = (*te.exps)[i];
891 if (i == 0)
892 einit = Expression.combine(te.e0, einit);
894 ti = new ExpInitializer(einit.loc, einit);
896 else
897 ti = dsym._init ? dsym._init.syntaxCopy() : null;
899 StorageClass storage_class = STC.temp | dsym.storage_class;
900 if ((dsym.storage_class & STC.parameter) && (arg.storageClass & STC.parameter))
901 storage_class |= arg.storageClass;
902 auto v = new VarDeclaration(dsym.loc, arg.type, id, ti, storage_class);
903 //printf("declaring field %s of type %s\n", v.toChars(), v.type.toChars());
904 v.overlapped = dsym.overlapped;
906 v.dsymbolSemantic(sc);
908 Expression e = new VarExp(dsym.loc, v);
909 (*exps)[i] = e;
911 auto v2 = new TupleDeclaration(dsym.loc, dsym.ident, exps);
912 v2.parent = dsym.parent;
913 v2.isexp = true;
914 dsym.aliasTuple = v2;
915 dsym.semanticRun = PASS.semanticdone;
916 return;
919 /* Storage class can modify the type
921 dsym.type = dsym.type.addStorageClass(dsym.storage_class);
923 /* Adjust storage class to reflect type
925 if (dsym.type.isConst())
927 dsym.storage_class |= STC.const_;
928 if (dsym.type.isShared())
929 dsym.storage_class |= STC.shared_;
931 else if (dsym.type.isImmutable())
932 dsym.storage_class |= STC.immutable_;
933 else if (dsym.type.isShared())
934 dsym.storage_class |= STC.shared_;
935 else if (dsym.type.isWild())
936 dsym.storage_class |= STC.wild;
938 if (StorageClass stc = dsym.storage_class & (STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_))
940 if (stc == STC.final_)
941 .error(dsym.loc, "%s `%s` cannot be `final`, perhaps you meant `const`?", dsym.kind, dsym.toPrettyChars);
942 else
944 OutBuffer buf;
945 stcToBuffer(buf, stc);
946 .error(dsym.loc, "%s `%s` cannot be `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
948 dsym.storage_class &= ~stc; // strip off
951 // At this point we can add `scope` to the STC instead of `in`,
952 // because we are never going to use this variable's STC for user messages
953 if (dsym.storage_class & STC.constscoperef)
954 dsym.storage_class |= STC.scope_;
956 if (dsym.storage_class & STC.scope_)
958 StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
959 if (stc)
961 OutBuffer buf;
962 stcToBuffer(buf, stc);
963 .error(dsym.loc, "%s `%s` cannot be `scope` and `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
965 else if (dsym.isMember())
967 error(dsym.loc, "field `%s` cannot be `scope`", dsym.toChars());
969 else if (!dsym.type.hasPointers())
971 dsym.storage_class &= ~STC.scope_; // silently ignore; may occur in generic code
972 // https://issues.dlang.org/show_bug.cgi?id=23168
973 if (dsym.storage_class & STC.returnScope)
975 dsym.storage_class &= ~(STC.return_ | STC.returnScope);
980 if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe))
983 else
985 AggregateDeclaration aad = parent.isAggregateDeclaration();
986 if (aad)
988 if (global.params.v.field && dsym.storage_class & (STC.const_ | STC.immutable_) && dsym._init && !dsym._init.isVoidInitializer())
990 const(char)* s = (dsym.storage_class & STC.immutable_) ? "immutable" : "const";
991 message(dsym.loc, "`%s.%s` is `%s` field", ad.toPrettyChars(), dsym.toChars(), s);
993 dsym.storage_class |= STC.field;
994 if (auto ts = tbn.isTypeStruct())
995 if (ts.sym.noDefaultCtor)
997 if (!dsym.isThisDeclaration() && !dsym._init)
998 aad.noDefaultCtor = true;
1002 InterfaceDeclaration id = parent.isInterfaceDeclaration();
1003 if (id)
1005 error(dsym.loc, "field `%s` not allowed in interface", dsym.toChars());
1007 else if (aad && aad.sizeok == Sizeok.done)
1009 error(dsym.loc, "cannot declare field `%s` because it will change the determined size of `%s`", dsym.toChars(), aad.toChars());
1012 /* Templates cannot add fields to aggregates
1014 TemplateInstance ti = parent.isTemplateInstance();
1015 if (ti)
1017 // Take care of nested templates
1018 while (1)
1020 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
1021 if (!ti2)
1022 break;
1023 ti = ti2;
1025 // If it's a member template
1026 AggregateDeclaration ad2 = ti.tempdecl.isMember();
1027 if (ad2 && dsym.storage_class != STC.undefined_)
1029 .error(dsym.loc, "%s `%s` - cannot use template to add field to aggregate `%s`", dsym.kind, dsym.toPrettyChars, ad2.toChars());
1034 /* If the alignment of a stack local is greater than the stack alignment,
1035 * note it in the enclosing function's alignSectionVars
1037 version (MARS)
1039 if (!dsym.alignment.isDefault() && sc.func &&
1040 dsym.alignment.get() > target.stackAlign() &&
1041 sc.func && !dsym.isDataseg() && !dsym.isParameter() && !dsym.isField())
1043 auto fd = sc.func;
1044 if (!fd.alignSectionVars)
1045 fd.alignSectionVars = new VarDeclarations();
1046 fd.alignSectionVars.push(dsym);
1050 if ((dsym.storage_class & (STC.ref_ | STC.parameter | STC.foreach_ | STC.temp | STC.result)) == STC.ref_ && dsym.ident != Id.This)
1052 .error(dsym.loc, "%s `%s` - only parameters, functions and `foreach` declarations can be `ref`", dsym.kind, dsym.toPrettyChars);
1055 if (dsym.type.hasWild())
1057 if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
1059 .error(dsym.loc, "%s `%s` - only parameters or stack-based variables can be `inout`", dsym.kind, dsym.toPrettyChars);
1061 FuncDeclaration func = sc.func;
1062 if (func)
1064 if (func.fes)
1065 func = func.fes.func;
1066 bool isWild = false;
1067 for (FuncDeclaration fd = func; fd; fd = fd.toParentDecl().isFuncDeclaration())
1069 if (fd.type.isTypeFunction().iswild)
1071 isWild = true;
1072 break;
1075 if (!isWild)
1077 .error(dsym.loc, "%s `%s` - `inout` variables can only be declared inside `inout` functions", dsym.kind, dsym.toPrettyChars);
1082 if (!(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.ref_ | STC.result)) &&
1083 tbn.ty == Tstruct && tbn.isTypeStruct().sym.noDefaultCtor)
1085 if (!dsym._init)
1087 if (dsym.isField())
1089 /* For fields, we'll check the constructor later to make sure it is initialized
1091 dsym.storage_class |= STC.nodefaultctor;
1093 else if (dsym.storage_class & STC.parameter)
1096 else
1097 .error(dsym.loc, "%s `%s` - default construction is disabled for type `%s`", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1101 FuncDeclaration fd = parent.isFuncDeclaration();
1102 if (dsym.type.isscope() && !(dsym.storage_class & STC.nodtor))
1104 if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.gshared) || !fd)
1106 .error(dsym.loc, "%s `%s` globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`", dsym.kind, dsym.toPrettyChars);
1109 // @@@DEPRECATED_2.097@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
1110 // Deprecated in 2.087
1111 // Remove this when the feature is removed from the language
1112 if (!(dsym.storage_class & STC.scope_))
1114 if (!(dsym.storage_class & STC.parameter) && dsym.ident != Id.withSym)
1115 .error(dsym.loc, "%s `%s` reference to `scope class` must be `scope`", dsym.kind, dsym.toPrettyChars);
1119 // Calculate type size + safety checks
1120 if (sc && sc.func)
1122 if (dsym._init && dsym._init.isVoidInitializer())
1125 if (dsym.type.hasPointers()) // also computes type size
1126 sc.setUnsafe(false, dsym.loc,
1127 "`void` initializers for pointers not allowed in safe functions");
1128 else if (dsym.type.hasInvariant())
1129 sc.setUnsafe(false, dsym.loc,
1130 "`void` initializers for structs with invariants are not allowed in safe functions");
1131 else if (dsym.type.hasSystemFields())
1132 sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc,
1133 "`void` initializers for `@system` variables not allowed in safe functions");
1135 else if (!dsym._init &&
1136 !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
1137 dsym.type.hasVoidInitPointers())
1139 sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions");
1143 if ((!dsym._init || dsym._init.isVoidInitializer) && !fd)
1145 // If not mutable, initializable by constructor only
1146 dsym.setInCtorOnly = true;
1149 if (dsym._init)
1150 { } // remember we had an explicit initializer
1151 else if (dsym.storage_class & STC.manifest)
1152 .error(dsym.loc, "%s `%s` - manifest constants must have initializers", dsym.kind, dsym.toPrettyChars);
1154 // Don't allow non-extern, non-__gshared variables to be interfaced with C++
1155 if (dsym._linkage == LINK.cpp && !(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.gshared)) && dsym.isDataseg())
1157 const char* p = (dsym.storage_class & STC.shared_) ? "shared" : "static";
1158 .error(dsym.loc, "%s `%s` cannot have `extern(C++)` linkage because it is `%s`", dsym.kind, dsym.toPrettyChars, p);
1159 errorSupplemental(dsym.loc, "perhaps declare it as `__gshared` instead");
1160 dsym.errors = true;
1163 bool isBlit = false;
1164 uinteger_t sz;
1165 if (sc.flags & SCOPE.Cfile && !dsym._init)
1167 addDefaultCInitializer(dsym);
1169 if (!dsym._init &&
1170 !(dsym.storage_class & (STC.static_ | STC.gshared | STC.extern_)) &&
1171 fd &&
1172 (!(dsym.storage_class & (STC.field | STC.in_ | STC.foreach_ | STC.parameter | STC.result)) ||
1173 (dsym.storage_class & STC.out_)) &&
1174 (sz = dsym.type.size()) != 0)
1176 // Provide a default initializer
1178 //printf("Providing default initializer for '%s'\n", dsym.toChars());
1179 if (sz == SIZE_INVALID && dsym.type.ty != Terror)
1180 .error(dsym.loc, "%s `%s` - size of type `%s` is invalid", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1182 Type tv = dsym.type;
1183 while (tv.ty == Tsarray) // Don't skip Tenum
1184 tv = tv.nextOf();
1185 if (tv.needsNested())
1187 /* Nested struct requires valid enclosing frame pointer.
1188 * In StructLiteralExp::toElem(), it's calculated.
1190 assert(tbn.ty == Tstruct);
1191 checkFrameAccess(dsym.loc, sc, tbn.isTypeStruct().sym);
1193 Expression e = tv.defaultInitLiteral(dsym.loc);
1194 e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1195 e = e.expressionSemantic(sc);
1196 dsym._init = new ExpInitializer(dsym.loc, e);
1197 goto Ldtor;
1199 if (tv.ty == Tstruct && tv.isTypeStruct().sym.zeroInit)
1201 /* If a struct is all zeros, as a special case
1202 * set its initializer to the integer 0.
1203 * In AssignExp::toElem(), we check for this and issue
1204 * a memset() to initialize the struct.
1205 * Must do same check in interpreter.
1207 Expression e = IntegerExp.literal!0;
1208 e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1209 e.type = dsym.type; // don't type check this, it would fail
1210 dsym._init = new ExpInitializer(dsym.loc, e);
1211 goto Ldtor;
1213 if (dsym.type.baseElemOf().ty == Tvoid)
1215 .error(dsym.loc, "%s `%s` of type `%s` does not have a default initializer", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
1217 else if (auto e = dsym.type.defaultInit(dsym.loc))
1219 dsym._init = new ExpInitializer(dsym.loc, e);
1222 // Default initializer is always a blit
1223 isBlit = true;
1225 if (dsym._init)
1227 sc = sc.push();
1228 sc.stc &= ~(STC.TYPECTOR | STC.pure_ | STC.nothrow_ | STC.nogc | STC.ref_ | STC.disable);
1230 if (sc.flags & SCOPE.Cfile &&
1231 dsym.type.isTypeSArray() &&
1232 dsym.type.isTypeSArray().isIncomplete() &&
1233 dsym._init.isVoidInitializer() &&
1234 !(dsym.storage_class & STC.field))
1236 .error(dsym.loc, "%s `%s` - incomplete array type must have initializer", dsym.kind, dsym.toPrettyChars);
1239 ExpInitializer ei = dsym._init.isExpInitializer();
1241 if (ei) // https://issues.dlang.org/show_bug.cgi?id=13424
1242 // Preset the required type to fail in FuncLiteralDeclaration::semantic3
1243 ei.exp = inferType(ei.exp, dsym.type);
1245 // If inside function, there is no semantic3() call
1246 if (sc.func || sc.intypeof == 1)
1248 // If local variable, use AssignExp to handle all the various
1249 // possibilities.
1250 if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
1252 //printf("fd = '%s', var = '%s'\n", fd.toChars(), dsym.toChars());
1253 if (!ei)
1255 ArrayInitializer ai = dsym._init.isArrayInitializer();
1256 Expression e;
1257 if (ai && tb.ty == Taarray)
1258 e = ai.toAssocArrayLiteral();
1259 else
1260 e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
1261 if (!e)
1263 // Run semantic, but don't need to interpret
1264 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITnointerpret);
1265 e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
1266 if (!e)
1268 .error(dsym.loc, "%s `%s` is not a static and cannot have static initializer", dsym.kind, dsym.toPrettyChars);
1269 e = ErrorExp.get();
1272 ei = new ExpInitializer(dsym._init.loc, e);
1273 dsym._init = ei;
1275 else if (sc.flags & SCOPE.Cfile && dsym.type.isTypeSArray() &&
1276 dsym.type.isTypeSArray().isIncomplete())
1278 // C11 6.7.9-22 determine the size of the incomplete array,
1279 // or issue an error that the initializer is invalid.
1280 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
1283 if (ei && dsym.isScope())
1285 Expression ex = ei.exp.lastComma();
1286 if (ex.op == EXP.blit || ex.op == EXP.construct)
1287 ex = (cast(AssignExp)ex).e2;
1288 if (auto ne = ex.isNewExp())
1290 /* See if initializer is a NewExp that can be allocated on the stack.
1292 if (dsym.type.toBasetype().ty == Tclass)
1294 /* Unsafe to allocate on stack if constructor is not `scope` because the `this` can leak.
1295 * https://issues.dlang.org/show_bug.cgi?id=23145
1297 if (ne.member && !(ne.member.storage_class & STC.scope_))
1299 import dmd.escape : setUnsafeDIP1000;
1300 const inSafeFunc = sc.func && sc.func.isSafeBypassingInference(); // isSafeBypassingInference may call setUnsafe().
1301 if (sc.setUnsafeDIP1000(false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym))
1302 errorSupplemental(ne.member.loc, "is the location of the constructor");
1304 ne.onstack = 1;
1305 dsym.onstack = true;
1308 else if (auto fe = ex.isFuncExp())
1310 // or a delegate that doesn't escape a reference to the function
1311 FuncDeclaration f = fe.fd;
1312 if (f.tookAddressOf)
1313 f.tookAddressOf--;
1315 else if (auto ale = ex.isArrayLiteralExp())
1317 // or an array literal assigned to a `scope` variable
1318 if (sc.useDIP1000 == FeatureState.enabled
1319 && !dsym.type.nextOf().needsDestruction())
1320 ale.onstack = true;
1324 Expression exp = ei.exp;
1325 Expression e1 = new VarExp(dsym.loc, dsym);
1326 if (isBlit)
1327 exp = new BlitExp(dsym.loc, e1, exp);
1328 else
1329 exp = new ConstructExp(dsym.loc, e1, exp);
1330 dsym.canassign++;
1331 exp = exp.expressionSemantic(sc);
1332 dsym.canassign--;
1333 exp = exp.optimize(WANTvalue);
1334 if (exp.op == EXP.error)
1336 dsym._init = new ErrorInitializer();
1337 ei = null;
1339 else
1340 ei.exp = exp;
1342 else
1344 // https://issues.dlang.org/show_bug.cgi?id=14166
1345 // Don't run CTFE for the temporary variables inside typeof
1346 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret);
1347 import dmd.semantic2 : lowerStaticAAs;
1348 lowerStaticAAs(dsym, sc);
1349 const init_err = dsym._init.isExpInitializer();
1350 if (init_err && init_err.exp.op == EXP.showCtfeContext)
1352 errorSupplemental(dsym.loc, "compile time context created here");
1356 else if (parent.isAggregateDeclaration())
1358 dsym._scope = scx ? scx : sc.copy();
1359 dsym._scope.setNoFree();
1361 else if (dsym.storage_class & (STC.const_ | STC.immutable_ | STC.manifest) ||
1362 dsym.type.isConst() || dsym.type.isImmutable() ||
1363 sc.flags & SCOPE.Cfile)
1365 /* Because we may need the results of a const declaration in a
1366 * subsequent type, such as an array dimension, before semantic2()
1367 * gets ordinarily run, try to run semantic2() now.
1368 * If a C array is of unknown size, the initializer can provide the size. Do this
1369 * eagerly because C does it eagerly.
1370 * Ignore failure.
1372 if (!inferred)
1374 uint errors = global.errors;
1375 dsym.inuse++;
1376 // Bug 20549. Don't try this on modules or packages, syntaxCopy
1377 // could crash (inf. recursion) on a mod/pkg referencing itself
1378 if (ei && (ei.exp.op != EXP.scope_ ? true : !ei.exp.isScopeExp().sds.isPackage()))
1380 if (ei.exp.type)
1382 // If exp is already resolved we are done, our original init exp
1383 // could have a type painting that we need to respect
1384 // e.g. ['a'] typed as string, or [['z'], ""] as string[]
1385 // See https://issues.dlang.org/show_bug.cgi?id=15711
1387 else
1389 Expression exp = ei.exp.syntaxCopy();
1391 bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
1392 if (needctfe)
1393 sc = sc.startCTFE();
1394 sc = sc.push();
1395 sc.varDecl = dsym; // https://issues.dlang.org/show_bug.cgi?id=24051
1396 exp = exp.expressionSemantic(sc);
1397 exp = resolveProperties(sc, exp);
1398 sc = sc.pop();
1399 if (needctfe)
1400 sc = sc.endCTFE();
1401 ei.exp = exp;
1404 Type tb2 = dsym.type.toBasetype();
1405 Type ti = ei.exp.type.toBasetype();
1407 /* The problem is the following code:
1408 * struct CopyTest {
1409 * double x;
1410 * this(double a) { x = a * 10.0;}
1411 * this(this) { x += 2.0; }
1413 * const CopyTest z = CopyTest(5.3); // ok
1414 * const CopyTest w = z; // not ok, postblit not run
1415 * static assert(w.x == 55.0);
1416 * because the postblit doesn't get run on the initialization of w.
1418 if (auto ts = ti.isTypeStruct())
1420 StructDeclaration sd = ts.sym;
1421 /* Look to see if initializer involves a copy constructor
1422 * (which implies a postblit)
1424 // there is a copy constructor
1425 // and exp is the same struct
1426 if (sd.postblit && tb2.toDsymbol(null) == sd)
1428 // The only allowable initializer is a (non-copy) constructor
1429 if (ei.exp.isLvalue())
1430 .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());
1435 dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
1436 dsym.inuse--;
1437 if (global.errors > errors)
1439 dsym._init = new ErrorInitializer();
1440 dsym.type = Type.terror;
1443 else
1445 dsym._scope = scx ? scx : sc.copy();
1446 dsym._scope.setNoFree();
1449 sc = sc.pop();
1452 Ldtor:
1453 /* Build code to execute destruction, if necessary
1455 dsym.edtor = dsym.callScopeDtor(sc);
1456 if (dsym.edtor)
1458 if (sc.func && dsym.storage_class & (STC.static_ | STC.gshared))
1459 dsym.edtor = dsym.edtor.expressionSemantic(sc._module._scope);
1460 else
1461 dsym.edtor = dsym.edtor.expressionSemantic(sc);
1463 version (none)
1465 // currently disabled because of std.stdio.stdin, stdout and stderr
1466 if (dsym.isDataseg() && !(dsym.storage_class & STC.extern_))
1467 .error(dsym.loc, "%s `%s` static storage variables cannot have destructors", dsym.kind, dsym.toPrettyChars);
1471 dsym.semanticRun = PASS.semanticdone;
1473 if (dsym.type.toBasetype().ty == Terror)
1474 dsym.errors = true;
1476 if(sc.scopesym && !sc.scopesym.isAggregateDeclaration())
1478 for (ScopeDsymbol sym = sc.scopesym; sym && dsym.endlinnum == 0;
1479 sym = sym.parent ? sym.parent.isScopeDsymbol() : null)
1480 dsym.endlinnum = sym.endlinnum;
1484 override void visit(TypeInfoDeclaration dsym)
1486 assert(dsym._linkage == LINK.c);
1489 override void visit(BitFieldDeclaration dsym)
1491 //printf("BitField::semantic('%s')\n", dsym.toChars());
1492 if (dsym.semanticRun >= PASS.semanticdone)
1493 return;
1495 visit(cast(VarDeclaration)dsym);
1496 if (dsym.errors)
1497 return;
1499 if (!(global.params.bitfields || sc.flags & SCOPE.Cfile))
1501 version (IN_GCC)
1502 .error(dsym.loc, "%s `%s` use `-fpreview=bitfields` for bitfield support", dsym.kind, dsym.toPrettyChars);
1503 else
1504 .error(dsym.loc, "%s `%s` use -preview=bitfields for bitfield support", dsym.kind, dsym.toPrettyChars);
1507 if (!dsym.parent.isStructDeclaration() && !dsym.parent.isClassDeclaration())
1509 .error(dsym.loc, "%s `%s` - bit-field must be member of struct, union, or class", dsym.kind, dsym.toPrettyChars);
1512 sc = sc.startCTFE();
1513 auto width = dsym.width.expressionSemantic(sc);
1514 sc = sc.endCTFE();
1515 width = width.ctfeInterpret();
1516 if (!dsym.type.isintegral())
1518 // C11 6.7.2.1-5
1519 error(width.loc, "bit-field type `%s` is not an integer type", dsym.type.toChars());
1520 dsym.errors = true;
1522 if (!width.isIntegerExp())
1524 error(width.loc, "bit-field width `%s` is not an integer constant", dsym.width.toChars());
1525 dsym.errors = true;
1527 const uwidth = width.toInteger(); // uwidth is unsigned
1528 if (uwidth == 0 && !dsym.isAnonymous())
1530 error(width.loc, "bit-field `%s` has zero width", dsym.toChars());
1531 dsym.errors = true;
1533 const sz = dsym.type.size();
1534 if (sz == SIZE_INVALID)
1535 dsym.errors = true;
1536 const max_width = sz * 8;
1537 if (uwidth > max_width)
1539 error(width.loc, "width `%lld` of bit-field `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
1540 dsym.errors = true;
1542 dsym.fieldWidth = cast(uint)uwidth;
1545 override void visit(Import imp)
1547 static if (LOG)
1549 printf("Import::semantic('%s') %s\n", imp.toPrettyChars(), imp.id.toChars());
1550 scope(exit)
1551 printf("-Import::semantic('%s'), pkg = %p\n", imp.toChars(), imp.pkg);
1553 if (imp.semanticRun > PASS.initial)
1554 return;
1556 if (imp._scope)
1558 sc = imp._scope;
1559 imp._scope = null;
1561 if (!sc)
1562 return;
1564 imp.parent = sc.parent;
1566 imp.semanticRun = PASS.semantic;
1568 // Load if not already done so
1569 if (!imp.mod)
1571 // https://issues.dlang.org/show_bug.cgi?id=22857
1572 // if parser errors occur when loading a module
1573 // we should just stop compilation
1574 if (imp.load(sc))
1576 for (size_t i = 0; i < imp.aliasdecls.length; i++)
1577 imp.aliasdecls[i].type = Type.terror;
1578 return;
1581 if (imp.mod)
1583 imp.mod.importAll(null);
1584 imp.mod.checkImportDeprecation(imp.loc, sc);
1587 if (imp.mod)
1589 // Modules need a list of each imported module
1591 // if inside a template instantiation, the instantianting
1592 // module gets the import.
1593 // https://issues.dlang.org/show_bug.cgi?id=17181
1594 Module importer = sc._module;
1595 if (sc.minst && sc.tinst)
1597 importer = sc.minst;
1598 if (!sc.tinst.importedModules.contains(imp.mod))
1599 sc.tinst.importedModules.push(imp.mod);
1601 //printf("%s imports %s\n", importer.toChars(), imp.mod.toChars());
1602 if (!importer.aimports.contains(imp.mod))
1603 importer.aimports.push(imp.mod);
1605 if (sc.explicitVisibility)
1606 imp.visibility = sc.visibility;
1608 if (!imp.aliasId && !imp.names.length) // neither a selective nor a renamed import
1610 ScopeDsymbol scopesym = sc.getScopesym();
1612 if (!imp.isstatic)
1614 scopesym.importScope(imp.mod, imp.visibility);
1618 imp.addPackageAccess(scopesym);
1621 // if a module has errors it means that parsing has failed.
1622 if (!imp.mod.errors)
1623 imp.mod.dsymbolSemantic(null);
1625 if (imp.mod.needmoduleinfo)
1627 //printf("module4 %s because of %s\n", importer.toChars(), imp.mod.toChars());
1628 importer.needmoduleinfo = 1;
1631 sc = sc.push(imp.mod);
1632 sc.visibility = imp.visibility;
1633 for (size_t i = 0; i < imp.aliasdecls.length; i++)
1635 AliasDeclaration ad = imp.aliasdecls[i];
1636 //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), aliases[i].toChars(), names[i].toChars(), ad._scope);
1637 Dsymbol sym = imp.mod.search(imp.loc, imp.names[i], SearchOpt.ignorePrivateImports);
1638 if (sym)
1640 import dmd.access : symbolIsVisible;
1641 if (!symbolIsVisible(sc, sym) && !sym.errors)
1643 .error(imp.loc, "%s `%s` member `%s` is not visible from module `%s`", imp.mod.kind, imp.mod.toPrettyChars,
1644 imp.names[i].toChars(), sc._module.toChars());
1645 sym.errors = true;
1647 ad.dsymbolSemantic(sc);
1648 // If the import declaration is in non-root module,
1649 // analysis of the aliased symbol is deferred.
1650 // Therefore, don't see the ad.aliassym or ad.type here.
1652 else
1654 Dsymbol s = imp.mod.search_correct(imp.names[i]);
1655 // https://issues.dlang.org/show_bug.cgi?id=23908
1656 // Don't suggest symbols from the importer's module
1657 if (s && s.parent != importer)
1658 .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());
1659 else
1660 .error(imp.loc, "%s `%s` import `%s` not found", imp.mod.kind, imp.mod.toPrettyChars, imp.names[i].toChars());
1661 ad.type = Type.terror;
1664 sc = sc.pop();
1667 imp.semanticRun = PASS.semanticdone;
1669 // object self-imports itself, so skip that
1670 // https://issues.dlang.org/show_bug.cgi?id=7547
1671 // don't list pseudo modules __entrypoint.d, __main.d
1672 // https://issues.dlang.org/show_bug.cgi?id=11117
1673 // https://issues.dlang.org/show_bug.cgi?id=11164
1674 if (global.params.moduleDeps.buffer is null || (imp.id == Id.object && sc._module.ident == Id.object) ||
1675 strcmp(sc._module.ident.toChars(), "__main") == 0)
1676 return;
1678 /* The grammar of the file is:
1679 * ImportDeclaration
1680 * ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
1681 * ModuleAliasIdentifier ] "\n"
1683 * BasicImportDeclaration
1684 * ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
1685 * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
1687 * FilePath
1688 * - any string with '(', ')' and '\' escaped with the '\' character
1690 OutBuffer* ob = global.params.moduleDeps.buffer;
1691 Module imod = sc._module;
1692 if (!global.params.moduleDeps.name)
1693 ob.writestring("depsImport ");
1694 ob.writestring(imod.toPrettyChars());
1695 ob.writestring(" (");
1696 escapePath(ob, imod.srcfile.toChars());
1697 ob.writestring(") : ");
1698 // use visibility instead of sc.visibility because it couldn't be
1699 // resolved yet, see the comment above
1700 visibilityToBuffer(*ob, imp.visibility);
1701 ob.writeByte(' ');
1702 if (imp.isstatic)
1704 stcToBuffer(*ob, STC.static_);
1705 ob.writeByte(' ');
1707 ob.writestring(": ");
1708 foreach (pid; imp.packages)
1710 ob.printf("%s.", pid.toChars());
1712 ob.writestring(imp.id.toString());
1713 ob.writestring(" (");
1714 if (imp.mod)
1715 escapePath(ob, imp.mod.srcfile.toChars());
1716 else
1717 ob.writestring("???");
1718 ob.writeByte(')');
1719 foreach (i, name; imp.names)
1721 if (i == 0)
1722 ob.writeByte(':');
1723 else
1724 ob.writeByte(',');
1725 Identifier _alias = imp.aliases[i];
1726 if (!_alias)
1728 ob.printf("%s", name.toChars());
1729 _alias = name;
1731 else
1732 ob.printf("%s=%s", _alias.toChars(), name.toChars());
1734 if (imp.aliasId)
1735 ob.printf(" -> %s", imp.aliasId.toChars());
1736 ob.writenl();
1739 void attribSemantic(AttribDeclaration ad)
1741 if (ad.semanticRun != PASS.initial)
1742 return;
1743 ad.semanticRun = PASS.semantic;
1744 Dsymbols* d = ad.include(sc);
1745 //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
1746 if (d)
1748 Scope* sc2 = ad.newScope(sc);
1749 bool errors;
1750 for (size_t i = 0; i < d.length; i++)
1752 Dsymbol s = (*d)[i];
1753 s.dsymbolSemantic(sc2);
1754 errors |= s.errors;
1756 ad.errors |= errors;
1757 if (sc2 != sc)
1758 sc2.pop();
1760 ad.semanticRun = PASS.semanticdone;
1763 override void visit(AttribDeclaration atd)
1765 attribSemantic(atd);
1768 override void visit(AnonDeclaration scd)
1770 //printf("\tAnonDeclaration::semantic isunion:%d ptr:%p\n", scd.isunion, scd);
1771 assert(sc.parent);
1772 auto p = sc.parent.pastMixin();
1773 auto ad = p.isAggregateDeclaration();
1774 if (!ad)
1776 error(scd.loc, "%s can only be a part of an aggregate, not %s `%s`", scd.kind(), p.kind(), p.toChars());
1777 scd.errors = true;
1778 return;
1781 if (!scd.decl)
1782 return;
1784 sc = sc.push();
1785 sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
1786 sc.inunion = scd.isunion ? scd : null;
1787 sc.flags = 0;
1788 for (size_t i = 0; i < scd.decl.length; i++)
1790 Dsymbol s = (*scd.decl)[i];
1791 if (auto var = s.isVarDeclaration)
1793 if (scd.isunion)
1794 var.overlapped = true;
1796 s.dsymbolSemantic(sc);
1798 sc = sc.pop();
1801 override void visit(PragmaDeclaration pd)
1803 StringExp verifyMangleString(ref Expression e)
1805 auto se = semanticString(sc, e, "mangled name");
1806 if (!se)
1807 return null;
1808 e = se;
1809 if (!se.len)
1811 .error(pd.loc, "%s `%s` - zero-length string not allowed for mangled name", pd.kind, pd.toPrettyChars);
1812 return null;
1814 if (se.sz != 1)
1816 .error(pd.loc, "%s `%s` - mangled name characters can only be of type `char`", pd.kind, pd.toPrettyChars);
1817 return null;
1819 version (all)
1821 /* Note: D language specification should not have any assumption about backend
1822 * implementation. Ideally pragma(mangle) can accept a string of any content.
1824 * Therefore, this validation is compiler implementation specific.
1826 auto slice = se.peekString();
1827 for (size_t i = 0; i < se.len;)
1829 dchar c = slice[i];
1830 if (c < 0x80)
1832 if (c.isValidMangling)
1834 ++i;
1835 continue;
1837 else
1839 .error(pd.loc, "%s `%s` char 0x%02x not allowed in mangled name", pd.kind, pd.toPrettyChars, c);
1840 break;
1843 if (const msg = utf_decodeChar(slice, i, c))
1845 .error(pd.loc, "%s `%s` %.*s", pd.kind, pd.toPrettyChars, cast(int)msg.length, msg.ptr);
1846 break;
1848 if (!isUniAlpha(c))
1850 .error(pd.loc, "%s `%s` char `0x%04x` not allowed in mangled name", pd.kind, pd.toPrettyChars, c);
1851 break;
1855 return se;
1857 void declarations()
1859 if (!pd.decl)
1860 return;
1862 Scope* sc2 = pd.newScope(sc);
1863 scope(exit)
1864 if (sc2 != sc)
1865 sc2.pop();
1867 foreach (s; (*pd.decl)[])
1869 if (pd.ident == Id.printf || pd.ident == Id.scanf)
1871 s.setPragmaPrintf(pd.ident == Id.printf);
1872 s.dsymbolSemantic(sc2);
1873 continue;
1876 s.dsymbolSemantic(sc2);
1877 if (pd.ident != Id.mangle)
1878 continue;
1879 assert(pd.args);
1880 if (auto ad = s.isAggregateDeclaration())
1882 Expression e = (*pd.args)[0];
1883 sc2 = sc2.startCTFE();
1884 e = e.expressionSemantic(sc);
1885 e = resolveProperties(sc2, e);
1886 sc2 = sc2.endCTFE();
1887 AggregateDeclaration agg;
1888 if (auto tc = e.type.isTypeClass())
1889 agg = tc.sym;
1890 else if (auto ts = e.type.isTypeStruct())
1891 agg = ts.sym;
1892 ad.pMangleOverride = new MangleOverride;
1893 void setString(ref Expression e)
1895 if (auto se = verifyMangleString(e))
1897 const name = (cast(const(char)[])se.peekData()).xarraydup;
1898 ad.pMangleOverride.id = Identifier.idPool(name);
1899 e = se;
1901 else
1902 error(e.loc, "must be a string");
1904 if (agg)
1906 ad.pMangleOverride.agg = agg;
1907 if (pd.args.length == 2)
1909 setString((*pd.args)[1]);
1911 else
1912 ad.pMangleOverride.id = agg.ident;
1914 else
1915 setString((*pd.args)[0]);
1917 else if (auto td = s.isTemplateDeclaration())
1919 .error(pd.loc, "%s `%s` cannot apply to a template declaration", pd.kind, pd.toPrettyChars);
1920 errorSupplemental(pd.loc, "use `template Class(Args...){ pragma(mangle, \"other_name\") class Class {} }`");
1922 else if (auto se = verifyMangleString((*pd.args)[0]))
1924 const name = (cast(const(char)[])se.peekData()).xarraydup;
1925 uint cnt = setMangleOverride(s, name);
1926 if (cnt > 1)
1927 .error(pd.loc, "%s `%s` can only apply to a single declaration", pd.kind, pd.toPrettyChars);
1932 void noDeclarations()
1934 if (pd.decl)
1936 .error(pd.loc, "%s `%s` is missing a terminating `;`", pd.kind, pd.toPrettyChars);
1937 declarations();
1938 // do them anyway, to avoid segfaults.
1942 // Should be merged with PragmaStatement
1943 //printf("\tPragmaDeclaration::semantic '%s'\n", pd.toChars());
1944 if (target.supportsLinkerDirective())
1946 if (pd.ident == Id.linkerDirective)
1948 if (!pd.args || pd.args.length != 1)
1949 .error(pd.loc, "%s `%s` one string argument expected for pragma(linkerDirective)", pd.kind, pd.toPrettyChars);
1950 else
1952 auto se = semanticString(sc, (*pd.args)[0], "linker directive");
1953 if (!se)
1954 return noDeclarations();
1955 (*pd.args)[0] = se;
1956 if (global.params.v.verbose)
1957 message("linkopt %.*s", cast(int)se.len, se.peekString().ptr);
1959 return noDeclarations();
1962 if (pd.ident == Id.msg)
1964 if (!pd.args)
1965 return noDeclarations();
1967 if (!pragmaMsgSemantic(pd.loc, sc, pd.args))
1968 return;
1970 return noDeclarations();
1972 else if (pd.ident == Id.lib)
1974 if (!pd.args || pd.args.length != 1)
1975 .error(pd.loc, "%s `%s` string expected for library name", pd.kind, pd.toPrettyChars);
1976 else
1978 auto se = semanticString(sc, (*pd.args)[0], "library name");
1979 if (!se)
1980 return noDeclarations();
1981 (*pd.args)[0] = se;
1983 auto name = se.peekString().xarraydup;
1984 if (global.params.v.verbose)
1985 message("library %s", name.ptr);
1986 if (global.params.moduleDeps.buffer && !global.params.moduleDeps.name)
1988 OutBuffer* ob = global.params.moduleDeps.buffer;
1989 Module imod = sc._module;
1990 ob.writestring("depsLib ");
1991 ob.writestring(imod.toPrettyChars());
1992 ob.writestring(" (");
1993 escapePath(ob, imod.srcfile.toChars());
1994 ob.writestring(") : ");
1995 ob.writestring(name);
1996 ob.writenl();
1998 mem.xfree(name.ptr);
2000 return noDeclarations();
2002 else if (pd.ident == Id.startaddress)
2004 pragmaStartAddressSemantic(pd.loc, sc, pd.args);
2005 return noDeclarations();
2007 else if (pd.ident == Id.Pinline)
2009 // this pragma now gets evaluated on demand in function semantic
2011 return declarations();
2013 else if (pd.ident == Id.mangle)
2015 if (!pd.args)
2016 pd.args = new Expressions();
2017 if (pd.args.length == 0 || pd.args.length > 2)
2019 .error(pd.loc, pd.args.length == 0 ? "%s `%s` - string expected for mangled name"
2020 : "%s `%s` expected 1 or 2 arguments", pd.kind, pd.toPrettyChars);
2021 pd.args.setDim(1);
2022 (*pd.args)[0] = ErrorExp.get(); // error recovery
2024 return declarations();
2026 else if (pd.ident == Id.crt_constructor || pd.ident == Id.crt_destructor)
2028 if (pd.args && pd.args.length != 0)
2029 .error(pd.loc, "%s `%s` takes no argument", pd.kind, pd.toPrettyChars);
2030 else
2032 immutable isCtor = pd.ident == Id.crt_constructor;
2034 static uint recurse(Dsymbol s, bool isCtor)
2036 if (auto ad = s.isAttribDeclaration())
2038 uint nestedCount;
2039 auto decls = ad.include(null);
2040 if (decls)
2042 for (size_t i = 0; i < decls.length; ++i)
2043 nestedCount += recurse((*decls)[i], isCtor);
2045 return nestedCount;
2047 else if (auto f = s.isFuncDeclaration())
2049 if (isCtor)
2050 f.isCrtCtor = true;
2051 else
2052 f.isCrtDtor = true;
2054 return 1;
2056 else
2057 return 0;
2058 assert(0);
2061 if (recurse(pd, isCtor) > 1)
2062 .error(pd.loc, "%s `%s` can only apply to a single declaration", pd.kind, pd.toPrettyChars);
2064 return declarations();
2066 else if (pd.ident == Id.printf || pd.ident == Id.scanf)
2068 if (pd.args && pd.args.length != 0)
2069 .error(pd.loc, "%s `%s` takes no argument", pd.kind, pd.toPrettyChars);
2070 return declarations();
2072 else if (!global.params.ignoreUnsupportedPragmas)
2074 error(pd.loc, "unrecognized `pragma(%s)`", pd.ident.toChars());
2075 return declarations();
2078 if (!global.params.v.verbose)
2079 return declarations();
2081 /* Print unrecognized pragmas
2083 OutBuffer buf;
2084 buf.writestring(pd.ident.toString());
2085 if (pd.args)
2087 const errors_save = global.startGagging();
2088 for (size_t i = 0; i < pd.args.length; i++)
2090 Expression e = (*pd.args)[i];
2091 sc = sc.startCTFE();
2092 e = e.expressionSemantic(sc);
2093 e = resolveProperties(sc, e);
2094 sc = sc.endCTFE();
2095 e = e.ctfeInterpret();
2096 if (i == 0)
2097 buf.writestring(" (");
2098 else
2099 buf.writeByte(',');
2100 buf.writestring(e.toChars());
2102 if (pd.args.length)
2103 buf.writeByte(')');
2104 global.endGagging(errors_save);
2106 message("pragma %s", buf.peekChars());
2107 return declarations();
2110 override void visit(StaticIfDeclaration sid)
2112 attribSemantic(sid);
2115 override void visit(StaticForeachDeclaration sfd)
2117 attribSemantic(sfd);
2120 private Dsymbols* compileIt(MixinDeclaration cd)
2122 //printf("MixinDeclaration::compileIt(loc = %d) %s\n", cd.loc.linnum, cd.exp.toChars());
2123 OutBuffer buf;
2124 if (expressionsToString(buf, sc, cd.exps))
2125 return null;
2127 const errors = global.errors;
2128 const len = buf.length;
2129 buf.writeByte(0);
2130 const str = buf.extractSlice()[0 .. len];
2131 const bool doUnittests = global.params.parsingUnittestsRequired();
2132 auto loc = adjustLocForMixin(str, cd.loc, global.params.mixinOut);
2133 scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
2134 p.transitionIn = global.params.v.vin;
2135 p.nextToken();
2137 auto d = p.parseDeclDefs(0);
2138 if (global.errors != errors)
2139 return null;
2141 if (p.token.value != TOK.endOfFile)
2143 .error(cd.loc, "%s `%s` incomplete mixin declaration `%s`", cd.kind, cd.toPrettyChars, str.ptr);
2144 return null;
2146 return d;
2149 /***********************************************************
2150 * https://dlang.org/spec/module.html#mixin-declaration
2152 override void visit(MixinDeclaration cd)
2154 //printf("MixinDeclaration::semantic()\n");
2155 if (!cd.compiled)
2157 cd.decl = compileIt(cd);
2158 attribAddMember(cd, sc, cd.scopesym);
2159 cd.compiled = true;
2161 if (cd._scope && cd.decl)
2163 for (size_t i = 0; i < cd.decl.length; i++)
2165 Dsymbol s = (*cd.decl)[i];
2166 s.setScope(cd._scope);
2170 attribSemantic(cd);
2173 override void visit(CPPNamespaceDeclaration ns)
2175 Identifier identFromSE (StringExp se)
2177 const sident = se.toStringz();
2178 if (!sident.length || !Identifier.isValidIdentifier(sident))
2180 error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%.*s`",
2181 cast(int)sident.length, sident.ptr);
2182 return null;
2184 else
2185 return Identifier.idPool(sident);
2188 if (ns.ident !is null)
2189 return attribSemantic(ns);
2191 ns.cppnamespace = sc.namespace;
2192 sc = sc.startCTFE();
2193 ns.exp = ns.exp.expressionSemantic(sc);
2194 ns.exp = resolveProperties(sc, ns.exp);
2195 sc = sc.endCTFE();
2196 ns.exp = ns.exp.ctfeInterpret();
2197 // Can be either a tuple of strings or a string itself
2198 if (auto te = ns.exp.isTupleExp())
2200 expandTuples(te.exps);
2201 CPPNamespaceDeclaration current = ns.cppnamespace;
2202 for (size_t d = 0; d < te.exps.length; ++d)
2204 auto exp = (*te.exps)[d];
2205 auto prev = d ? current : ns.cppnamespace;
2206 current = (d + 1) != te.exps.length
2207 ? new CPPNamespaceDeclaration(ns.loc, exp, null)
2208 : ns;
2209 current.exp = exp;
2210 current.cppnamespace = prev;
2211 if (auto se = exp.toStringExp())
2213 current.ident = identFromSE(se);
2214 if (current.ident is null)
2215 return; // An error happened in `identFromSE`
2217 else
2218 error(ns.exp.loc, "`%s`: index %llu is not a string constant, it is a `%s`",
2219 ns.exp.toChars(), cast(ulong) d, ns.exp.type.toChars());
2222 else if (auto se = ns.exp.toStringExp())
2223 ns.ident = identFromSE(se);
2224 // Empty Tuple
2225 else if (ns.exp.isTypeExp() && ns.exp.isTypeExp().type.toBasetype().isTypeTuple())
2228 else if (!ns.exp.type.isTypeError())
2229 error(ns.exp.loc, "compile time string constant (or sequence) expected, not `%s`",
2230 ns.exp.toChars());
2231 attribSemantic(ns);
2234 override void visit(UserAttributeDeclaration uad)
2236 //printf("UserAttributeDeclaration::semantic() %p\n", this);
2237 if (uad.decl && !uad._scope)
2238 uad.Dsymbol.setScope(sc); // for function local symbols
2239 arrayExpressionSemantic(uad.atts.peekSlice(), sc, true);
2240 return attribSemantic(uad);
2243 override void visit(StaticAssert sa)
2245 if (sa.semanticRun < PASS.semanticdone)
2246 sa.semanticRun = PASS.semanticdone;
2249 override void visit(DebugSymbol ds)
2251 //printf("DebugSymbol::semantic() %s\n", toChars());
2252 if (ds.semanticRun < PASS.semanticdone)
2253 ds.semanticRun = PASS.semanticdone;
2256 override void visit(VersionSymbol vs)
2258 if (vs.semanticRun < PASS.semanticdone)
2259 vs.semanticRun = PASS.semanticdone;
2262 override void visit(Package pkg)
2264 if (pkg.semanticRun < PASS.semanticdone)
2265 pkg.semanticRun = PASS.semanticdone;
2268 override void visit(Module m)
2270 if (m.semanticRun != PASS.initial)
2271 return;
2272 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
2273 m.semanticRun = PASS.semantic;
2274 // Note that modules get their own scope, from scratch.
2275 // This is so regardless of where in the syntax a module
2276 // gets imported, it is unaffected by context.
2277 Scope* sc = m._scope; // see if already got one from importAll()
2278 if (!sc)
2280 sc = Scope.createGlobal(m, global.errorSink); // create root scope
2283 //printf("Module = %p, linkage = %d\n", sc.scopesym, sc.linkage);
2284 // Pass 1 semantic routines: do public side of the definition
2285 m.members.foreachDsymbol( (s)
2287 //printf("\tModule('%s'): '%s'.dsymbolSemantic()\n", toChars(), s.toChars());
2288 s.dsymbolSemantic(sc);
2289 m.runDeferredSemantic();
2292 if (m.userAttribDecl)
2294 m.userAttribDecl.dsymbolSemantic(sc);
2296 if (!m._scope)
2298 sc = sc.pop();
2299 sc.pop(); // 2 pops because Scope.createGlobal() created 2
2301 m.semanticRun = PASS.semanticdone;
2302 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
2305 override void visit(EnumDeclaration ed)
2307 enumSemantic(sc, ed);
2310 override void visit(EnumMember em)
2312 enumMemberSemantic(sc, em);
2315 override void visit(TemplateDeclaration tempdecl)
2317 static if (LOG)
2319 printf("TemplateDeclaration.dsymbolSemantic(this = %p, id = '%s')\n", this, tempdecl.ident.toChars());
2320 printf("sc.stc = %llx\n", sc.stc);
2321 printf("sc.module = %s\n", sc._module.toChars());
2323 if (tempdecl.semanticRun != PASS.initial)
2324 return; // semantic() already run
2326 if (tempdecl._scope)
2328 sc = tempdecl._scope;
2329 tempdecl._scope = null;
2331 if (!sc)
2332 return;
2334 // Remember templates defined in module object that we need to know about
2335 if (sc._module && sc._module.ident == Id.object)
2337 if (tempdecl.ident == Id.RTInfo)
2338 Type.rtinfo = tempdecl;
2341 /* Remember Scope for later instantiations, but make
2342 * a copy since attributes can change.
2344 if (!tempdecl._scope)
2346 tempdecl._scope = sc.copy();
2347 tempdecl._scope.setNoFree();
2350 tempdecl.semanticRun = PASS.semantic;
2352 tempdecl.parent = sc.parent;
2353 tempdecl.visibility = sc.visibility;
2354 tempdecl.userAttribDecl = sc.userAttribDecl;
2355 tempdecl.cppnamespace = sc.namespace;
2356 tempdecl.isstatic = tempdecl.toParent().isModule() || (tempdecl._scope.stc & STC.static_);
2357 tempdecl.deprecated_ = !!(sc.stc & STC.deprecated_);
2359 UserAttributeDeclaration.checkGNUABITag(tempdecl, sc.linkage);
2361 if (!tempdecl.isstatic)
2363 if (auto ad = tempdecl.parent.pastMixin().isAggregateDeclaration())
2364 ad.makeNested();
2367 // Set up scope for parameters
2368 auto paramsym = new ScopeDsymbol();
2369 paramsym.parent = tempdecl.parent;
2370 Scope* paramscope = sc.push(paramsym);
2371 paramscope.stc = 0;
2373 if (global.params.ddoc.doOutput)
2375 tempdecl.origParameters = new TemplateParameters(tempdecl.parameters.length);
2376 for (size_t i = 0; i < tempdecl.parameters.length; i++)
2378 TemplateParameter tp = (*tempdecl.parameters)[i];
2379 (*tempdecl.origParameters)[i] = tp.syntaxCopy();
2383 for (size_t i = 0; i < tempdecl.parameters.length; i++)
2385 TemplateParameter tp = (*tempdecl.parameters)[i];
2386 if (!tp.declareParameter(paramscope))
2388 error(tp.loc, "parameter `%s` multiply defined", tp.ident.toChars());
2389 tempdecl.errors = true;
2391 if (!tp.tpsemantic(paramscope, tempdecl.parameters))
2393 tempdecl.errors = true;
2395 if (i + 1 != tempdecl.parameters.length && tp.isTemplateTupleParameter())
2397 .error(tempdecl.loc, "%s `%s` template sequence parameter must be the last one", tempdecl.kind, tempdecl.toPrettyChars);
2398 tempdecl.errors = true;
2402 /* Calculate TemplateParameter.dependent
2404 TemplateParameters tparams = TemplateParameters(1);
2405 for (size_t i = 0; i < tempdecl.parameters.length; i++)
2407 TemplateParameter tp = (*tempdecl.parameters)[i];
2408 tparams[0] = tp;
2410 for (size_t j = 0; j < tempdecl.parameters.length; j++)
2412 // Skip cases like: X(T : T)
2413 if (i == j)
2414 continue;
2416 if (TemplateTypeParameter ttp = (*tempdecl.parameters)[j].isTemplateTypeParameter())
2418 if (reliesOnTident(ttp.specType, &tparams))
2419 tp.dependent = true;
2421 else if (TemplateAliasParameter tap = (*tempdecl.parameters)[j].isTemplateAliasParameter())
2423 if (reliesOnTident(tap.specType, &tparams) ||
2424 reliesOnTident(isType(tap.specAlias), &tparams))
2426 tp.dependent = true;
2432 paramscope.pop();
2434 // Compute again
2435 tempdecl.onemember = null;
2436 if (tempdecl.members)
2438 Dsymbol s;
2439 if (Dsymbol.oneMembers(tempdecl.members, s, tempdecl.ident) && s)
2441 tempdecl.onemember = s;
2442 s.parent = tempdecl;
2446 /* BUG: should check:
2447 * 1. template functions must not introduce virtual functions, as they
2448 * cannot be accomodated in the vtbl[]
2449 * 2. templates cannot introduce non-static data members (i.e. fields)
2450 * as they would change the instance size of the aggregate.
2453 tempdecl.semanticRun = PASS.semanticdone;
2456 override void visit(TemplateInstance ti)
2458 templateInstanceSemantic(ti, sc, ArgumentList());
2461 override void visit(TemplateMixin tm)
2463 static if (LOG)
2465 printf("+TemplateMixin.dsymbolSemantic('%s', this=%p)\n", tm.toChars(), tm);
2466 fflush(stdout);
2468 if (tm.semanticRun != PASS.initial)
2470 // When a class/struct contains mixin members, and is done over
2471 // because of forward references, never reach here so semanticRun
2472 // has been reset to PASS.initial.
2473 static if (LOG)
2475 printf("\tsemantic done\n");
2477 return;
2479 tm.semanticRun = PASS.semantic;
2480 static if (LOG)
2482 printf("\tdo semantic\n");
2485 Scope* scx = null;
2486 if (tm._scope)
2488 sc = tm._scope;
2489 scx = tm._scope; // save so we don't make redundant copies
2490 tm._scope = null;
2493 /* Run semantic on each argument, place results in tiargs[],
2494 * then find best match template with tiargs
2496 if (!tm.findTempDecl(sc) || !tm.semanticTiargs(sc) || !tm.findBestMatch(sc, ArgumentList()))
2498 if (tm.semanticRun == PASS.initial) // forward reference had occurred
2500 //printf("forward reference - deferring\n");
2501 return deferDsymbolSemantic(sc, tm, scx);
2504 tm.inst = tm;
2505 tm.errors = true;
2506 return; // error recovery
2509 auto tempdecl = tm.tempdecl.isTemplateDeclaration();
2510 assert(tempdecl);
2512 if (!tm.ident)
2514 /* Assign scope local unique identifier, as same as lambdas.
2516 const(char)[] s = "__mixin";
2518 if (FuncDeclaration func = sc.parent.isFuncDeclaration())
2520 tm.symtab = func.localsymtab;
2521 if (tm.symtab)
2523 // Inside template constraint, symtab is not set yet.
2524 goto L1;
2527 else
2529 tm.symtab = sc.parent.isScopeDsymbol().symtab;
2531 assert(tm.symtab);
2532 tm.ident = Identifier.generateId(s, tm.symtab.length + 1);
2533 tm.symtab.insert(tm);
2537 tm.inst = tm;
2538 tm.parent = sc.parent;
2540 /* Detect recursive mixin instantiations.
2542 for (Dsymbol s = tm.parent; s; s = s.parent)
2544 //printf("\ts = '%s'\n", s.toChars());
2545 TemplateMixin tmix = s.isTemplateMixin();
2546 if (!tmix || tempdecl != tmix.tempdecl)
2547 continue;
2549 /* Different argument list lengths happen with variadic args
2551 if (tm.tiargs.length != tmix.tiargs.length)
2552 continue;
2554 for (size_t i = 0; i < tm.tiargs.length; i++)
2556 RootObject o = (*tm.tiargs)[i];
2557 Type ta = isType(o);
2558 Expression ea = isExpression(o);
2559 Dsymbol sa = isDsymbol(o);
2560 RootObject tmo = (*tmix.tiargs)[i];
2561 if (ta)
2563 Type tmta = isType(tmo);
2564 if (!tmta)
2565 goto Lcontinue;
2566 if (!ta.equals(tmta))
2567 goto Lcontinue;
2569 else if (ea)
2571 Expression tme = isExpression(tmo);
2572 if (!tme || !ea.equals(tme))
2573 goto Lcontinue;
2575 else if (sa)
2577 Dsymbol tmsa = isDsymbol(tmo);
2578 if (sa != tmsa)
2579 goto Lcontinue;
2581 else
2582 assert(0);
2584 .error(tm.loc, "%s `%s` recursive mixin instantiation", tm.kind, tm.toPrettyChars);
2585 return;
2587 Lcontinue:
2588 continue;
2591 // Copy the syntax trees from the TemplateDeclaration
2592 tm.members = Dsymbol.arraySyntaxCopy(tempdecl.members);
2593 if (!tm.members)
2594 return;
2596 tm.symtab = new DsymbolTable();
2598 sc.getScopesym().importScope(tm, Visibility(Visibility.Kind.public_));
2600 static if (LOG)
2602 printf("\tcreate scope for template parameters '%s'\n", tm.toChars());
2604 Scope* scy = sc.push(tm);
2605 scy.parent = tm;
2607 /* https://issues.dlang.org/show_bug.cgi?id=930
2609 * If the template that is to be mixed in is in the scope of a template
2610 * instance, we have to also declare the type aliases in the new mixin scope.
2612 auto parentInstance = tempdecl.parent ? tempdecl.parent.isTemplateInstance() : null;
2613 if (parentInstance)
2614 parentInstance.declareParameters(scy);
2616 tm.argsym = new ScopeDsymbol();
2617 tm.argsym.parent = scy.parent;
2618 Scope* argscope = scy.push(tm.argsym);
2620 uint errorsave = global.errors;
2622 // Declare each template parameter as an alias for the argument type
2623 tm.declareParameters(argscope);
2625 // Add members to enclosing scope, as well as this scope
2626 tm.members.foreachDsymbol(s => s.addMember(argscope, tm));
2628 // Do semantic() analysis on template instance members
2629 static if (LOG)
2631 printf("\tdo semantic() on template instance members '%s'\n", tm.toChars());
2633 Scope* sc2 = argscope.push(tm);
2634 //size_t deferred_dim = Module.deferred.length;
2636 __gshared int nest;
2637 //printf("%d\n", nest);
2638 if (++nest > global.recursionLimit)
2640 global.gag = 0; // ensure error message gets printed
2641 .error(tm.loc, "%s `%s` recursive expansion", tm.kind, tm.toPrettyChars);
2642 fatal();
2645 tm.members.foreachDsymbol( s => s.setScope(sc2) );
2647 tm.members.foreachDsymbol( s => s.importAll(sc2) );
2649 tm.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
2651 nest--;
2653 /* In DeclDefs scope, TemplateMixin does not have to handle deferred symbols.
2654 * Because the members would already call Module.addDeferredSemantic() for themselves.
2655 * See Struct, Class, Interface, and EnumDeclaration.dsymbolSemantic().
2657 //if (!sc.func && Module.deferred.length > deferred_dim) {}
2659 AggregateDeclaration ad = tm.isMember();
2660 if (sc.func && !ad)
2662 tm.semantic2(sc2);
2663 tm.semantic3(sc2);
2666 // Give additional context info if error occurred during instantiation
2667 if (global.errors != errorsave)
2669 .error(tm.loc, "%s `%s` error instantiating", tm.kind, tm.toPrettyChars);
2670 tm.errors = true;
2673 sc2.pop();
2674 argscope.pop();
2675 scy.pop();
2677 static if (LOG)
2679 printf("-TemplateMixin.dsymbolSemantic('%s', this=%p)\n", tm.toChars(), tm);
2683 override void visit(Nspace ns)
2685 if (ns.semanticRun != PASS.initial)
2686 return;
2687 static if (LOG)
2689 printf("+Nspace::semantic('%s')\n", ns.toChars());
2690 scope(exit) printf("-Nspace::semantic('%s')\n", ns.toChars());
2692 if (ns._scope)
2694 sc = ns._scope;
2695 ns._scope = null;
2697 if (!sc)
2698 return;
2700 bool repopulateMembers = false;
2701 if (ns.identExp)
2703 // resolve the namespace identifier
2704 sc = sc.startCTFE();
2705 Expression resolved = ns.identExp.expressionSemantic(sc);
2706 resolved = resolveProperties(sc, resolved);
2707 sc = sc.endCTFE();
2708 resolved = resolved.ctfeInterpret();
2709 StringExp name = resolved.toStringExp();
2710 TupleExp tup = name ? null : resolved.isTupleExp();
2711 if (!tup && !name)
2713 error(ns.loc, "expected string expression for namespace name, got `%s`", ns.identExp.toChars());
2714 return;
2716 ns.identExp = resolved; // we don't need to keep the old AST around
2717 if (name)
2719 const(char)[] ident = name.toStringz();
2720 if (ident.length == 0 || !Identifier.isValidIdentifier(ident))
2722 error(ns.loc, "expected valid identifier for C++ namespace but got `%.*s`", cast(int)ident.length, ident.ptr);
2723 return;
2725 ns.ident = Identifier.idPool(ident);
2727 else
2729 // create namespace stack from the tuple
2730 Nspace parentns = ns;
2731 foreach (i, exp; *tup.exps)
2733 name = exp.toStringExp();
2734 if (!name)
2736 error(ns.loc, "expected string expression for namespace name, got `%s`", exp.toChars());
2737 return;
2739 const(char)[] ident = name.toStringz();
2740 if (ident.length == 0 || !Identifier.isValidIdentifier(ident))
2742 error(ns.loc, "expected valid identifier for C++ namespace but got `%.*s`", cast(int)ident.length, ident.ptr);
2743 return;
2745 if (i == 0)
2747 ns.ident = Identifier.idPool(ident);
2749 else
2751 // insert the new namespace
2752 Nspace childns = new Nspace(ns.loc, Identifier.idPool(ident), null, parentns.members);
2753 parentns.members = new Dsymbols;
2754 parentns.members.push(childns);
2755 parentns = childns;
2756 repopulateMembers = true;
2762 ns.semanticRun = PASS.semantic;
2763 ns.parent = sc.parent;
2764 // Link does not matter here, if the UDA is present it will error
2765 UserAttributeDeclaration.checkGNUABITag(ns, LINK.cpp);
2767 if (!ns.members)
2769 ns.semanticRun = PASS.semanticdone;
2770 return;
2772 assert(sc);
2773 sc = sc.push(ns);
2774 sc.linkage = LINK.cpp; // note that namespaces imply C++ linkage
2775 sc.parent = ns;
2776 foreach (s; *ns.members)
2778 if (repopulateMembers)
2780 s.addMember(sc, sc.scopesym);
2781 s.setScope(sc);
2783 s.importAll(sc);
2785 foreach (s; *ns.members)
2787 static if (LOG)
2789 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
2791 s.dsymbolSemantic(sc);
2793 sc.pop();
2794 ns.semanticRun = PASS.semanticdone;
2797 void funcDeclarationSemantic(FuncDeclaration funcdecl)
2799 version (none)
2801 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, funcdecl, funcdecl.toPrettyChars(), sc.linkage);
2802 if (funcdecl.isFuncLiteralDeclaration())
2803 printf("\tFuncLiteralDeclaration()\n");
2804 printf("sc.parent = %s, parent = %s\n", sc.parent.toChars(), funcdecl.parent ? funcdecl.parent.toChars() : "");
2805 printf("type: %p, %s\n", funcdecl.type, funcdecl.type.toChars());
2808 if (funcdecl.semanticRun != PASS.initial && funcdecl.isFuncLiteralDeclaration())
2810 /* Member functions that have return types that are
2811 * forward references can have semantic() run more than
2812 * once on them.
2813 * See test\interface2.d, test20
2815 return;
2818 if (funcdecl.semanticRun >= PASS.semanticdone)
2819 return;
2820 assert(funcdecl.semanticRun <= PASS.semantic);
2821 funcdecl.semanticRun = PASS.semantic;
2823 if (funcdecl._scope)
2825 sc = funcdecl._scope;
2826 funcdecl._scope = null;
2829 if (!sc || funcdecl.errors)
2830 return;
2832 funcdecl.cppnamespace = sc.namespace;
2833 funcdecl.parent = sc.parent;
2834 Dsymbol parent = funcdecl.toParent();
2836 funcdecl.foverrides.setDim(0); // reset in case semantic() is being retried for this function
2838 funcdecl.storage_class |= sc.stc & ~STC.ref_;
2839 AggregateDeclaration ad = funcdecl.isThis();
2840 // Don't nest structs b/c of generated methods which should not access the outer scopes.
2841 // https://issues.dlang.org/show_bug.cgi?id=16627
2842 if (ad && !funcdecl.isGenerated())
2844 funcdecl.storage_class |= ad.storage_class & (STC.TYPECTOR | STC.synchronized_);
2845 ad.makeNested();
2847 if (sc.func)
2848 funcdecl.storage_class |= sc.func.storage_class & STC.disable;
2849 // Remove prefix storage classes silently.
2850 if ((funcdecl.storage_class & STC.TYPECTOR) && !(ad || funcdecl.isNested()))
2851 funcdecl.storage_class &= ~STC.TYPECTOR;
2853 //printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal());
2855 if (sc.flags & SCOPE.compile)
2856 funcdecl.skipCodegen = true;
2858 funcdecl._linkage = sc.linkage;
2859 if (sc.flags & SCOPE.Cfile && funcdecl.isFuncLiteralDeclaration())
2860 funcdecl._linkage = LINK.d; // so they are uniquely mangled
2862 if (auto fld = funcdecl.isFuncLiteralDeclaration())
2864 if (fld.treq)
2866 Type treq = fld.treq;
2867 assert(treq.nextOf().ty == Tfunction);
2868 if (treq.ty == Tdelegate)
2869 fld.tok = TOK.delegate_;
2870 else if (treq.isPtrToFunction())
2871 fld.tok = TOK.function_;
2872 else
2873 assert(0);
2874 funcdecl._linkage = treq.nextOf().toTypeFunction().linkage;
2878 // evaluate pragma(inline)
2879 if (auto pragmadecl = sc.inlining)
2880 funcdecl.inlining = evalPragmaInline(pragmadecl.loc, sc, pragmadecl.args);
2882 funcdecl.visibility = sc.visibility;
2883 funcdecl.userAttribDecl = sc.userAttribDecl;
2884 UserAttributeDeclaration.checkGNUABITag(funcdecl, funcdecl._linkage);
2885 checkMustUseReserved(funcdecl);
2887 if (!funcdecl.originalType)
2888 funcdecl.originalType = funcdecl.type.syntaxCopy();
2890 static TypeFunction getFunctionType(FuncDeclaration fd)
2892 if (auto tf = fd.type.isTypeFunction())
2893 return tf;
2895 if (!fd.type.isTypeError())
2897 .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars());
2898 fd.type = Type.terror;
2900 fd.errors = true;
2901 return null;
2904 if (sc.flags & SCOPE.Cfile)
2906 /* C11 allows a function to be declared with a typedef, D does not.
2908 if (auto ti = funcdecl.type.isTypeIdentifier())
2910 auto tj = ti.typeSemantic(funcdecl.loc, sc);
2911 if (auto tjf = tj.isTypeFunction())
2913 /* Copy the type instead of just pointing to it,
2914 * as we don't merge function types
2916 auto tjf2 = new TypeFunction(tjf.parameterList, tjf.next, tjf.linkage);
2917 funcdecl.type = tjf2;
2918 funcdecl.originalType = tjf2;
2923 if (!getFunctionType(funcdecl))
2924 return;
2926 if (!funcdecl.type.deco)
2928 sc = sc.push();
2929 sc.stc |= funcdecl.storage_class & (STC.disable | STC.deprecated_); // forward to function type
2931 TypeFunction tf = funcdecl.type.toTypeFunction();
2932 if (sc.func)
2934 /* If the nesting parent is pure without inference,
2935 * then this function defaults to pure too.
2937 * auto foo() pure {
2938 * auto bar() {} // become a weak purity function
2939 * class C { // nested class
2940 * auto baz() {} // become a weak purity function
2943 * static auto boo() {} // typed as impure
2944 * // Even though, boo cannot call any impure functions.
2945 * // See also Expression::checkPurity().
2948 if (tf.purity == PURE.impure && (funcdecl.isNested() || funcdecl.isThis()))
2950 FuncDeclaration fd = null;
2951 for (Dsymbol p = funcdecl.toParent2(); p; p = p.toParent2())
2953 if (AggregateDeclaration adx = p.isAggregateDeclaration())
2955 if (adx.isNested())
2956 continue;
2957 break;
2959 if ((fd = p.isFuncDeclaration()) !is null)
2960 break;
2963 /* If the parent's purity is inferred, then this function's purity needs
2964 * to be inferred first.
2966 if (fd && fd.isPureBypassingInference() >= PURE.weak && !funcdecl.isInstantiated())
2968 tf.purity = PURE.fwdref; // default to pure
2973 if (tf.isref)
2974 sc.stc |= STC.ref_;
2975 if (tf.isScopeQual)
2976 sc.stc |= STC.scope_;
2977 if (tf.isnothrow)
2978 sc.stc |= STC.nothrow_;
2979 if (tf.isnogc)
2980 sc.stc |= STC.nogc;
2981 if (tf.isproperty)
2982 sc.stc |= STC.property;
2983 if (tf.purity == PURE.fwdref)
2984 sc.stc |= STC.pure_;
2986 if (tf.trust != TRUST.default_)
2988 sc.stc &= ~STC.safeGroup;
2989 if (tf.trust == TRUST.safe)
2990 sc.stc |= STC.safe;
2991 else if (tf.trust == TRUST.system)
2992 sc.stc |= STC.system;
2993 else if (tf.trust == TRUST.trusted)
2994 sc.stc |= STC.trusted;
2997 if (funcdecl.isCtorDeclaration())
2999 tf.isctor = true;
3000 Type tret = ad.handleType();
3001 assert(tret);
3002 tret = tret.addStorageClass(funcdecl.storage_class | sc.stc);
3003 tret = tret.addMod(funcdecl.type.mod);
3004 tf.next = tret;
3005 if (ad.isStructDeclaration())
3006 sc.stc |= STC.ref_;
3009 // 'return' on a non-static class member function implies 'scope' as well
3010 if (ad && ad.isClassDeclaration() && (tf.isreturn || sc.stc & STC.return_) && !(sc.stc & STC.static_))
3011 sc.stc |= STC.scope_;
3013 // If 'this' has no pointers, remove 'scope' as it has no meaning
3014 // Note: this is already covered by semantic of `VarDeclaration` and `TypeFunction`,
3015 // but existing code relies on `hasPointers()` being called here to resolve forward references:
3016 // https://github.com/dlang/dmd/pull/14232#issuecomment-1162906573
3017 if (sc.stc & STC.scope_ && ad && ad.isStructDeclaration() && !ad.type.hasPointers())
3019 sc.stc &= ~STC.scope_;
3020 tf.isScopeQual = false;
3021 if (tf.isreturnscope)
3023 sc.stc &= ~(STC.return_ | STC.returnScope);
3024 tf.isreturn = false;
3025 tf.isreturnscope = false;
3029 sc.linkage = funcdecl._linkage;
3031 if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested()))
3033 import core.bitop : popcnt;
3034 auto mods = MODtoChars(tf.mod);
3035 .error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, mods);
3036 if (tf.next && tf.next.ty != Tvoid && popcnt(tf.mod) == 1)
3037 .errorSupplemental(funcdecl.loc,
3038 "did you mean to use `%s(%s)` as the return type?", mods, tf.next.toChars());
3040 tf.mod = 0; // remove qualifiers
3043 /* Apply const, immutable, wild and shared storage class
3044 * to the function type. Do this before type semantic.
3046 auto stc = funcdecl.storage_class;
3047 if (funcdecl.type.isImmutable())
3048 stc |= STC.immutable_;
3049 if (funcdecl.type.isConst())
3050 stc |= STC.const_;
3051 if (funcdecl.type.isShared() || funcdecl.storage_class & STC.synchronized_)
3052 stc |= STC.shared_;
3053 if (funcdecl.type.isWild())
3054 stc |= STC.wild;
3055 funcdecl.type = funcdecl.type.addSTC(stc);
3057 funcdecl.type = funcdecl.type.typeSemantic(funcdecl.loc, sc);
3058 sc = sc.pop();
3061 auto f = getFunctionType(funcdecl);
3062 if (!f)
3063 return; // funcdecl's type is not a function
3066 // Merge back function attributes into 'originalType'.
3067 // It's used for mangling, ddoc, and json output.
3068 TypeFunction tfo = funcdecl.originalType.toTypeFunction();
3069 tfo.mod = f.mod;
3070 tfo.isScopeQual = f.isScopeQual;
3071 tfo.isreturninferred = f.isreturninferred;
3072 tfo.isscopeinferred = f.isscopeinferred;
3073 tfo.isref = f.isref;
3074 tfo.isnothrow = f.isnothrow;
3075 tfo.isnogc = f.isnogc;
3076 tfo.isproperty = f.isproperty;
3077 tfo.purity = f.purity;
3078 tfo.trust = f.trust;
3080 funcdecl.storage_class &= ~(STC.TYPECTOR | STC.FUNCATTR);
3083 // check pragma(crt_constructor) signature
3084 if (funcdecl.isCrtCtor || funcdecl.isCrtDtor)
3086 const idStr = funcdecl.isCrtCtor ? "crt_constructor" : "crt_destructor";
3087 if (f.nextOf().ty != Tvoid)
3088 .error(funcdecl.loc, "%s `%s` must return `void` for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
3089 if (funcdecl._linkage != LINK.c && f.parameterList.length != 0)
3090 .error(funcdecl.loc, "%s `%s` must be `extern(C)` for `pragma(%s)` when taking parameters", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
3091 if (funcdecl.isThis())
3092 .error(funcdecl.loc, "%s `%s` cannot be a non-static member function for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
3095 if (funcdecl.overnext && funcdecl.isCsymbol())
3097 /* C does not allow function overloading, but it does allow
3098 * redeclarations of the same function. If .overnext points
3099 * to a redeclaration, ok. Error if it is an overload.
3101 auto fnext = funcdecl.overnext.isFuncDeclaration();
3102 funcDeclarationSemantic(fnext);
3103 auto fn = fnext.type.isTypeFunction();
3104 if (!fn || !cFuncEquivalence(f, fn))
3106 .error(funcdecl.loc, "%s `%s` redeclaration with different type", funcdecl.kind, funcdecl.toPrettyChars);
3107 //printf("t1: %s\n", f.toChars());
3108 //printf("t2: %s\n", fn.toChars());
3110 funcdecl.overnext = null; // don't overload the redeclarations
3113 if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
3114 .error(funcdecl.loc, "%s `%s` storage class `auto` has no effect if return type is not inferred", funcdecl.kind, funcdecl.toPrettyChars);
3116 if (f.isreturn && !funcdecl.needThis() && !funcdecl.isNested())
3118 /* Non-static nested functions have a hidden 'this' pointer to which
3119 * the 'return' applies
3121 if (sc.scopesym && sc.scopesym.isAggregateDeclaration())
3122 .error(funcdecl.loc, "%s `%s` `static` member has no `this` to which `return` can apply", funcdecl.kind, funcdecl.toPrettyChars);
3123 else
3124 error(funcdecl.loc, "top-level function `%s` has no `this` to which `return` can apply", funcdecl.toChars());
3127 if (funcdecl.isAbstract() && !funcdecl.isVirtual())
3129 const(char)* sfunc;
3130 if (funcdecl.isStatic())
3131 sfunc = "static";
3132 else if (funcdecl.visibility.kind == Visibility.Kind.private_ || funcdecl.visibility.kind == Visibility.Kind.package_)
3133 sfunc = visibilityToChars(funcdecl.visibility.kind);
3134 else
3135 sfunc = "final";
3136 .error(funcdecl.loc, "%s `%s` `%s` functions cannot be `abstract`", funcdecl.kind, funcdecl.toPrettyChars, sfunc);
3139 if (funcdecl.isOverride() && !funcdecl.isVirtual() && !funcdecl.isFuncLiteralDeclaration())
3141 Visibility.Kind kind = funcdecl.visible().kind;
3142 if ((kind == Visibility.Kind.private_ || kind == Visibility.Kind.package_) && funcdecl.isMember())
3143 .error(funcdecl.loc, "%s `%s` `%s` method is not virtual and cannot override", funcdecl.kind, funcdecl.toPrettyChars, visibilityToChars(kind));
3144 else
3145 .error(funcdecl.loc, "%s `%s` cannot override a non-virtual function", funcdecl.kind, funcdecl.toPrettyChars);
3148 if (funcdecl.isAbstract() && funcdecl.isFinalFunc())
3149 .error(funcdecl.loc, "%s `%s` cannot be both `final` and `abstract`", funcdecl.kind, funcdecl.toPrettyChars);
3151 if (funcdecl.printf || funcdecl.scanf)
3153 checkPrintfScanfSignature(funcdecl, f, sc);
3156 if (auto id = parent.isInterfaceDeclaration())
3158 funcdecl.storage_class |= STC.abstract_;
3159 if (funcdecl.isCtorDeclaration() || funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration() || funcdecl.isNewDeclaration() || funcdecl.isDelete())
3160 .error(funcdecl.loc, "%s `%s` constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
3161 if (funcdecl.fbody && funcdecl.isVirtual())
3162 .error(funcdecl.loc, "%s `%s` function body only allowed in `final` functions in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
3165 if (UnionDeclaration ud = parent.isUnionDeclaration())
3167 if (funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration())
3168 .error(funcdecl.loc, "%s `%s` destructors, postblits and invariants are not allowed in union `%s`", funcdecl.kind, funcdecl.toPrettyChars, ud.toChars());
3171 if (StructDeclaration sd = parent.isStructDeclaration())
3173 if (funcdecl.isCtorDeclaration())
3175 goto Ldone;
3179 if (ClassDeclaration cd = parent.isClassDeclaration())
3181 parent = cd = objc.getParent(funcdecl, cd);
3183 if (funcdecl.isCtorDeclaration())
3185 goto Ldone;
3188 if (funcdecl.storage_class & STC.abstract_)
3189 cd.isabstract = ThreeState.yes;
3191 // if static function, do not put in vtbl[]
3192 if (!funcdecl.isVirtual())
3194 //printf("\tnot virtual\n");
3195 goto Ldone;
3197 // Suppress further errors if the return type is an error
3198 if (funcdecl.type.nextOf() == Type.terror)
3199 goto Ldone;
3201 bool may_override = false;
3202 for (size_t i = 0; i < cd.baseclasses.length; i++)
3204 BaseClass* b = (*cd.baseclasses)[i];
3205 ClassDeclaration cbd = b.type.toBasetype().isClassHandle();
3206 if (!cbd)
3207 continue;
3208 for (size_t j = 0; j < cbd.vtbl.length; j++)
3210 FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration();
3211 if (!f2 || f2.ident != funcdecl.ident)
3212 continue;
3213 if (cbd.parent && cbd.parent.isTemplateInstance())
3215 if (!functionSemantic(f2))
3216 goto Ldone;
3218 may_override = true;
3221 if (may_override && funcdecl.type.nextOf() is null)
3223 /* If same name function exists in base class but 'this' is auto return,
3224 * cannot find index of base class's vtbl[] to override.
3226 .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars);
3229 /* Find index of existing function in base class's vtbl[] to override
3230 * (the index will be the same as in cd's current vtbl[])
3232 int vi = cd.baseClass ? funcdecl.findVtblIndex(&cd.baseClass.vtbl, cast(int)cd.baseClass.vtbl.length) : -1;
3234 bool doesoverride = false;
3235 switch (vi)
3237 case -1:
3238 Lintro:
3239 /* Didn't find one, so
3240 * This is an 'introducing' function which gets a new
3241 * slot in the vtbl[].
3244 // Verify this doesn't override previous final function
3245 if (cd.baseClass)
3247 Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident);
3248 if (s)
3250 if (auto f2 = s.isFuncDeclaration())
3252 f2 = f2.overloadExactMatch(funcdecl.type);
3253 if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
3254 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars());
3259 /* These quirky conditions mimic what happens when virtual
3260 inheritance is implemented by producing a virtual base table
3261 with offsets to each of the virtual bases.
3263 if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
3264 cd.baseClass && cd.baseClass.vtbl.length)
3266 /* if overriding an interface function, then this is not
3267 * introducing and don't put it in the class vtbl[]
3269 funcdecl.interfaceVirtual = funcdecl.overrideInterface();
3270 if (funcdecl.interfaceVirtual)
3272 //printf("\tinterface function %s\n", toChars());
3273 cd.vtblFinal.push(funcdecl);
3274 goto Linterfaces;
3278 if (funcdecl.isFinalFunc())
3280 // Don't check here, as it may override an interface function
3281 //if (isOverride())
3282 // error("is marked as override, but does not override any function");
3283 cd.vtblFinal.push(funcdecl);
3285 else
3287 //printf("\tintroducing function %s\n", funcdecl.toChars());
3288 funcdecl.isIntroducing = true;
3289 if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads)
3291 /* Overloaded functions with same name are grouped and in reverse order.
3292 * Search for first function of overload group, and insert
3293 * funcdecl into vtbl[] immediately before it.
3295 funcdecl.vtblIndex = cast(int)cd.vtbl.length;
3296 bool found;
3297 foreach (const i, s; cd.vtbl)
3299 if (found)
3300 // the rest get shifted forward
3301 ++s.isFuncDeclaration().vtblIndex;
3302 else if (s.ident == funcdecl.ident && s.parent == parent)
3304 // found first function of overload group
3305 funcdecl.vtblIndex = cast(int)i;
3306 found = true;
3307 ++s.isFuncDeclaration().vtblIndex;
3310 cd.vtbl.insert(funcdecl.vtblIndex, funcdecl);
3312 debug foreach (const i, s; cd.vtbl)
3314 // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl),
3315 // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception.
3316 if (auto fd = s.isFuncDeclaration())
3317 assert(fd.vtblIndex == i ||
3318 (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration) ||
3319 funcdecl.parent.isInterfaceDeclaration); // interface functions can be in multiple vtbls
3322 else
3324 // Append to end of vtbl[]
3325 vi = cast(int)cd.vtbl.length;
3326 cd.vtbl.push(funcdecl);
3327 funcdecl.vtblIndex = vi;
3330 break;
3332 case -2:
3333 // can't determine because of forward references
3334 funcdecl.errors = true;
3335 return;
3337 default:
3339 if (vi >= cd.vtbl.length)
3341 /* the derived class cd doesn't have its vtbl[] allocated yet.
3342 * https://issues.dlang.org/show_bug.cgi?id=21008
3344 .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
3345 funcdecl.errors = true;
3346 return;
3348 FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration();
3349 FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration();
3350 // This function is covariant with fdv
3352 if (fdc == funcdecl)
3354 doesoverride = true;
3355 break;
3358 auto vtf = getFunctionType(fdv);
3359 if (vtf.trust > TRUST.system && f.trust == TRUST.system)
3360 .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars,
3361 fdv.toPrettyChars);
3363 if (fdc.toParent() == parent)
3365 //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
3366 // vi, this, this.toChars(), this.type.toChars(), this.loc.toChars(),
3367 // fdc, fdc .toChars(), fdc .type.toChars(), fdc .loc.toChars(),
3368 // fdv, fdv .toChars(), fdv .type.toChars(), fdv .loc.toChars());
3370 // fdc overrides fdv exactly, then this introduces new function.
3371 if (fdc.type.mod == fdv.type.mod && funcdecl.type.mod != fdv.type.mod)
3372 goto Lintro;
3375 if (fdv.isDeprecated && !funcdecl.isDeprecated)
3376 deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`",
3377 funcdecl.toPrettyChars, fdv.toPrettyChars);
3379 // This function overrides fdv
3380 if (fdv.isFinalFunc())
3381 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars());
3383 if (!funcdecl.isOverride())
3385 if (fdv.isFuture())
3387 deprecation(funcdecl.loc, "`@__future` base class method `%s` is being overridden by `%s`; rename the latter", fdv.toPrettyChars(), funcdecl.toPrettyChars());
3388 // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
3389 goto Lintro;
3391 else
3393 // https://issues.dlang.org/show_bug.cgi?id=17349
3394 error(funcdecl.loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
3395 fdv.toPrettyChars(), funcdecl.toPrettyChars());
3398 doesoverride = true;
3399 if (fdc.toParent() == parent)
3401 // If both are mixins, or both are not, then error.
3402 // If either is not, the one that is not overrides the other.
3403 bool thismixin = funcdecl.parent.isClassDeclaration() !is null;
3404 bool fdcmixin = fdc.parent.isClassDeclaration() !is null;
3405 if (thismixin == fdcmixin)
3407 .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars);
3410 * https://issues.dlang.org/show_bug.cgi?id=711
3412 * If an overriding method is introduced through a mixin,
3413 * we need to update the vtbl so that both methods are
3414 * present.
3416 else if (thismixin)
3418 /* if the mixin introduced the overriding method, then reintroduce it
3419 * in the vtbl. The initial entry for the mixined method
3420 * will be updated at the end of the enclosing `if` block
3421 * to point to the current (non-mixined) function.
3423 auto vitmp = cast(int)cd.vtbl.length;
3424 cd.vtbl.push(fdc);
3425 fdc.vtblIndex = vitmp;
3427 else if (fdcmixin)
3429 /* if the current overriding function is coming from a
3430 * mixined block, then push the current function in the
3431 * vtbl, but keep the previous (non-mixined) function as
3432 * the overriding one.
3434 auto vitmp = cast(int)cd.vtbl.length;
3435 cd.vtbl.push(funcdecl);
3436 funcdecl.vtblIndex = vitmp;
3437 break;
3439 else // fdc overrides fdv
3441 // this doesn't override any function
3442 break;
3445 cd.vtbl[vi] = funcdecl;
3446 funcdecl.vtblIndex = vi;
3448 /* Remember which functions this overrides
3450 funcdecl.foverrides.push(fdv);
3452 /* This works by whenever this function is called,
3453 * it actually returns tintro, which gets dynamically
3454 * cast to type. But we know that tintro is a base
3455 * of type, so we could optimize it by not doing a
3456 * dynamic cast, but just subtracting the isBaseOf()
3457 * offset if the value is != null.
3460 if (fdv.tintro)
3461 funcdecl.tintro = fdv.tintro;
3462 else if (!funcdecl.type.equals(fdv.type))
3464 auto tnext = funcdecl.type.nextOf();
3465 if (auto handle = tnext.isClassHandle())
3467 if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
3468 handle.dsymbolSemantic(null);
3470 /* Only need to have a tintro if the vptr
3471 * offsets differ
3473 int offset;
3474 if (fdv.type.nextOf().isBaseOf(tnext, &offset))
3476 funcdecl.tintro = fdv.type;
3479 break;
3483 /* Go through all the interface bases.
3484 * If this function is covariant with any members of those interface
3485 * functions, set the tintro.
3487 Linterfaces:
3488 bool foundVtblMatch = false;
3490 for (ClassDeclaration bcd = cd; !foundVtblMatch && bcd; bcd = bcd.baseClass)
3492 foreach (b; bcd.interfaces)
3494 vi = funcdecl.findVtblIndex(&b.sym.vtbl, cast(int)b.sym.vtbl.length);
3495 switch (vi)
3497 case -1:
3498 break;
3500 case -2:
3501 // can't determine because of forward references
3502 funcdecl.errors = true;
3503 return;
3505 default:
3507 auto fdv = cast(FuncDeclaration)b.sym.vtbl[vi];
3508 Type ti = null;
3510 foundVtblMatch = true;
3512 /* Remember which functions this overrides
3514 funcdecl.foverrides.push(fdv);
3516 if (fdv.tintro)
3517 ti = fdv.tintro;
3518 else if (!funcdecl.type.equals(fdv.type))
3520 /* Only need to have a tintro if the vptr
3521 * offsets differ
3523 int offset;
3524 if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset))
3526 ti = fdv.type;
3529 if (ti)
3531 if (funcdecl.tintro)
3533 if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null))
3535 .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars());
3538 else
3540 funcdecl.tintro = ti;
3547 if (foundVtblMatch)
3549 goto L2;
3552 if (!doesoverride && funcdecl.isOverride() && (funcdecl.type.nextOf() || !may_override))
3554 BaseClass* bc = null;
3555 Dsymbol s = null;
3556 for (size_t i = 0; i < cd.baseclasses.length; i++)
3558 bc = (*cd.baseclasses)[i];
3559 s = bc.sym.search_correct(funcdecl.ident);
3560 if (s)
3561 break;
3564 if (s)
3566 HdrGenState hgs;
3567 OutBuffer buf;
3569 auto fd = s.isFuncDeclaration();
3570 functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf,
3571 new Identifier(funcdecl.toPrettyChars()), hgs, null);
3572 const(char)* funcdeclToChars = buf.peekChars();
3574 if (fd)
3576 OutBuffer buf1;
3578 if (fd.ident == funcdecl.ident)
3579 hgs.fullQual = true;
3581 // https://issues.dlang.org/show_bug.cgi?id=23745
3582 // If the potentially overridden function contains errors,
3583 // inform the user to fix that one first
3584 if (fd.errors)
3586 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
3587 funcdecl.toChars(), fd.toPrettyChars());
3588 errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden",
3589 fd.toPrettyChars());
3591 else
3593 functionToBufferFull(cast(TypeFunction)(fd.type), buf1,
3594 new Identifier(fd.toPrettyChars()), hgs, null);
3596 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
3597 funcdeclToChars, buf1.peekChars());
3600 else
3602 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?",
3603 funcdeclToChars, s.kind, s.toPrettyChars());
3604 errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden");
3607 else
3608 .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars);
3612 objc.setSelector(funcdecl, sc);
3613 objc.checkLinkage(funcdecl);
3614 objc.addToClassMethodList(funcdecl, cd);
3615 objc.setAsOptional(funcdecl, sc);
3617 /* Go through all the interface bases.
3618 * Disallow overriding any final functions in the interface(s).
3620 foreach (b; cd.interfaces)
3622 if (b.sym)
3624 if (auto s = search_function(b.sym, funcdecl.ident))
3626 if (auto f2 = s.isFuncDeclaration())
3628 f2 = f2.overloadExactMatch(funcdecl.type);
3629 if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
3630 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars());
3636 if (funcdecl.isOverride)
3638 if (funcdecl.storage_class & STC.disable)
3639 deprecation(funcdecl.loc,
3640 "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class",
3641 funcdecl.toPrettyChars);
3643 if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated))
3644 deprecation(funcdecl.loc,
3645 "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class",
3646 funcdecl.toPrettyChars);
3650 else if (funcdecl.isOverride() && !parent.isTemplateInstance())
3651 .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars);
3653 if (auto ti = parent.isTemplateInstance)
3655 objc.setSelector(funcdecl, sc);
3656 objc.setAsOptional(funcdecl, sc);
3659 objc.validateSelector(funcdecl);
3660 objc.validateOptional(funcdecl);
3661 // Reflect this.type to f because it could be changed by findVtblIndex
3662 f = funcdecl.type.toTypeFunction();
3664 Ldone:
3665 if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody())
3666 .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars);
3668 /* Do not allow template instances to add virtual functions
3669 * to a class.
3671 if (funcdecl.isVirtual())
3673 if (auto ti = parent.isTemplateInstance())
3675 // Take care of nested templates
3676 while (1)
3678 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
3679 if (!ti2)
3680 break;
3681 ti = ti2;
3684 // If it's a member template
3685 ClassDeclaration cd = ti.tempdecl.isClassMember();
3686 if (cd)
3688 .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
3693 funcdecl.checkMain(); // Check main() parameters and return type
3695 /* Purity and safety can be inferred for some functions by examining
3696 * the function body.
3698 if (funcdecl.canInferAttributes(sc))
3699 funcdecl.initInferAttributes();
3701 funcdecl.semanticRun = PASS.semanticdone;
3703 /* Save scope for possible later use (if we need the
3704 * function internals)
3706 funcdecl._scope = sc.copy();
3707 funcdecl._scope.setNoFree();
3709 __gshared bool printedMain = false; // semantic might run more than once
3710 if (global.params.v.verbose && !printedMain)
3712 const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null;
3713 Module mod = sc._module;
3715 if (type && mod)
3717 printedMain = true;
3718 auto name = mod.srcfile.toChars();
3719 auto path = FileName.searchPath(global.path, name, true);
3720 message("entry %-10s\t%s", type, path ? path : name);
3724 if (funcdecl.fbody && sc._module.isRoot() &&
3725 (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain()))
3726 global.hasMainFunction = true;
3728 if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot())
3730 // check if `_d_cmain` is defined
3731 bool cmainTemplateExists()
3733 Dsymbol pscopesym;
3734 auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym);
3735 if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object))
3736 if (moduleSymbol.search(funcdecl.loc, Id.CMain))
3737 return true;
3739 return false;
3742 // Only mixin `_d_cmain` if it is defined
3743 if (cmainTemplateExists())
3745 // add `mixin _d_cmain!();` to the declaring module
3746 auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain);
3747 auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null);
3748 sc._module.members.push(tm);
3752 assert(funcdecl.type.ty != Terror || funcdecl.errors);
3754 // semantic for parameters' UDAs
3755 foreach (i, param; f.parameterList)
3757 if (param && param.userAttribDecl)
3758 param.userAttribDecl.dsymbolSemantic(sc);
3762 /// Do the semantic analysis on the external interface to the function.
3763 override void visit(FuncDeclaration funcdecl)
3765 funcDeclarationSemantic(funcdecl);
3768 override void visit(CtorDeclaration ctd)
3770 //printf("CtorDeclaration::semantic() %s\n", toChars());
3771 if (ctd.semanticRun >= PASS.semanticdone)
3772 return;
3773 if (ctd._scope)
3775 sc = ctd._scope;
3776 ctd._scope = null;
3779 ctd.parent = sc.parent;
3780 Dsymbol p = ctd.toParentDecl();
3781 AggregateDeclaration ad = p.isAggregateDeclaration();
3782 if (!ad)
3784 error(ctd.loc, "constructor can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
3785 ctd.type = Type.terror;
3786 ctd.errors = true;
3787 return;
3790 sc = sc.push();
3792 if (sc.stc & STC.static_)
3794 if (sc.stc & STC.shared_)
3795 error(ctd.loc, "`shared static` has no effect on a constructor inside a `shared static` block. Use `shared static this()`");
3796 else
3797 error(ctd.loc, "`static` has no effect on a constructor inside a `static` block. Use `static this()`");
3800 sc.stc &= ~STC.static_; // not a static constructor
3802 funcDeclarationSemantic(ctd);
3804 sc.pop();
3806 if (ctd.errors)
3807 return;
3809 TypeFunction tf = ctd.type.toTypeFunction();
3810 immutable dim = tf.parameterList.length;
3811 auto sd = ad.isStructDeclaration();
3813 /* See if it's the default constructor
3814 * But, template constructor should not become a default constructor.
3816 if (ad && (!ctd.parent.isTemplateInstance() || ctd.parent.isTemplateMixin()))
3818 if (!sd)
3820 if (dim == 0 && tf.parameterList.varargs == VarArg.none)
3821 ad.defaultCtor = ctd;
3822 return;
3825 if (dim == 0 && tf.parameterList.varargs == VarArg.none) // empty default ctor w/o any varargs
3827 if (ctd.fbody || !(ctd.storage_class & STC.disable))
3829 .error(ctd.loc, "%s `%s` default constructor for structs only allowed " ~
3830 "with `@disable`, no body, and no parameters", ctd.kind, ctd.toPrettyChars);
3831 ctd.storage_class |= STC.disable;
3832 ctd.fbody = null;
3834 sd.noDefaultCtor = true;
3836 else if (dim == 0 && tf.parameterList.varargs != VarArg.none) // allow varargs only ctor
3839 else if (dim && !tf.parameterList.hasArgsWithoutDefault)
3841 if (ctd.storage_class & STC.disable)
3843 .error(ctd.loc, "%s `%s` is marked `@disable`, so it cannot have default "~
3844 "arguments for all parameters.", ctd.kind, ctd.toPrettyChars);
3845 errorSupplemental(ctd.loc, "Use `@disable this();` if you want to disable default initialization.");
3847 else
3848 .error(ctd.loc, "%s `%s` all parameters have default arguments, "~
3849 "but structs cannot have default constructors.", ctd.kind, ctd.toPrettyChars);
3851 else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
3853 //printf("tf: %s\n", tf.toChars());
3854 auto param = tf.parameterList[0];
3855 if (param.storageClass & STC.ref_ && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
3857 //printf("copy constructor\n");
3858 ctd.isCpCtor = true;
3862 // https://issues.dlang.org/show_bug.cgi?id=22593
3863 else if (auto ti = ctd.parent.isTemplateInstance())
3865 checkHasBothRvalueAndCpCtor(sd, ctd, ti);
3869 override void visit(PostBlitDeclaration pbd)
3871 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
3872 //printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor);
3873 //printf("stc = x%llx\n", sc.stc);
3874 if (pbd.semanticRun >= PASS.semanticdone)
3875 return;
3876 if (pbd._scope)
3878 sc = pbd._scope;
3879 pbd._scope = null;
3882 pbd.parent = sc.parent;
3883 Dsymbol p = pbd.toParent2();
3884 StructDeclaration ad = p.isStructDeclaration();
3885 if (!ad)
3887 error(pbd.loc, "postblit can only be a member of struct, not %s `%s`", p.kind(), p.toChars());
3888 pbd.type = Type.terror;
3889 pbd.errors = true;
3890 return;
3892 if (pbd.ident == Id.postblit && pbd.semanticRun < PASS.semantic)
3893 ad.postblits.push(pbd);
3894 if (!pbd.type)
3895 pbd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, pbd.storage_class);
3897 sc = sc.push();
3898 sc.stc &= ~STC.static_; // not static
3899 sc.linkage = LINK.d;
3901 funcDeclarationSemantic(pbd);
3903 sc.pop();
3906 override void visit(DtorDeclaration dd)
3908 //printf("DtorDeclaration::semantic() %s\n", dd.toChars());
3909 //printf("ident: %s, %s, %p, %p\n", dd.ident.toChars(), Id.dtor.toChars(), dd.ident, Id.dtor);
3910 if (dd.semanticRun >= PASS.semanticdone)
3911 return;
3912 if (dd._scope)
3914 sc = dd._scope;
3915 dd._scope = null;
3918 dd.parent = sc.parent;
3919 Dsymbol p = dd.toParent2();
3920 AggregateDeclaration ad = p.isAggregateDeclaration();
3921 if (!ad)
3923 error(dd.loc, "destructor can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
3924 dd.type = Type.terror;
3925 dd.errors = true;
3926 return;
3929 if (ad.isClassDeclaration() && ad.classKind == ClassKind.d)
3931 // Class destructors are implicitly `scope`
3932 dd.storage_class |= STC.scope_;
3935 if (dd.ident == Id.dtor && dd.semanticRun < PASS.semantic)
3936 ad.userDtors.push(dd);
3937 if (!dd.type)
3939 dd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, dd.storage_class);
3940 if (ad.classKind == ClassKind.cpp && dd.ident == Id.dtor)
3942 if (auto cldec = ad.isClassDeclaration())
3944 assert (cldec.cppDtorVtblIndex == -1); // double-call check already by dd.type
3945 if (cldec.baseClass && cldec.baseClass.cppDtorVtblIndex != -1)
3947 // override the base virtual
3948 cldec.cppDtorVtblIndex = cldec.baseClass.cppDtorVtblIndex;
3950 else if (!dd.isFinal())
3952 // reserve the dtor slot for the destructor (which we'll create later)
3953 cldec.cppDtorVtblIndex = cast(int)cldec.vtbl.length;
3954 cldec.vtbl.push(dd);
3955 if (target.cpp.twoDtorInVtable)
3956 cldec.vtbl.push(dd); // deleting destructor uses a second slot
3962 sc = sc.push();
3963 sc.stc &= ~STC.static_; // not a static destructor
3964 if (sc.linkage != LINK.cpp)
3965 sc.linkage = LINK.d;
3967 funcDeclarationSemantic(dd);
3969 sc.pop();
3972 override void visit(StaticCtorDeclaration scd)
3974 //printf("StaticCtorDeclaration::semantic()\n");
3975 if (scd.semanticRun >= PASS.semanticdone)
3976 return;
3977 if (scd._scope)
3979 sc = scd._scope;
3980 scd._scope = null;
3983 scd.parent = sc.parent;
3984 Dsymbol p = scd.parent.pastMixin();
3985 if (!p.isScopeDsymbol())
3987 const(char)* s = (scd.isSharedStaticCtorDeclaration() ? "shared " : "");
3988 error(scd.loc, "`%sstatic` constructor can only be member of module/aggregate/template, not %s `%s`", s, p.kind(), p.toChars());
3989 scd.type = Type.terror;
3990 scd.errors = true;
3991 return;
3993 if (!scd.type)
3994 scd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, scd.storage_class);
3996 /* If the static ctor appears within a template instantiation,
3997 * it could get called multiple times by the module constructors
3998 * for different modules. Thus, protect it with a gate.
4000 if (scd.isInstantiated() && scd.semanticRun < PASS.semantic)
4002 /* Add this prefix to the constructor:
4003 * ```
4004 * static int gate;
4005 * if (++gate != 1) return;
4006 * ```
4007 * or, for shared constructor:
4008 * ```
4009 * shared int gate;
4010 * if (core.atomic.atomicOp!"+="(gate, 1) != 1) return;
4011 * ```
4013 const bool isShared = !!scd.isSharedStaticCtorDeclaration();
4014 auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
4015 v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
4017 auto sa = new Statements();
4018 Statement s = new ExpStatement(Loc.initial, v);
4019 sa.push(s);
4021 Expression e;
4022 if (isShared)
4024 e = doAtomicOp("+=", v.ident, IntegerExp.literal!(1));
4025 if (e is null)
4027 .error(scd.loc, "%s `%s` shared static constructor within a template require `core.atomic : atomicOp` to be present", scd.kind, scd.toPrettyChars);
4028 return;
4031 else
4033 e = new AddAssignExp(
4034 Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!1);
4037 e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!1);
4038 s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
4040 sa.push(s);
4041 if (scd.fbody)
4042 sa.push(scd.fbody);
4044 scd.fbody = new CompoundStatement(Loc.initial, sa);
4047 const LINK save = sc.linkage;
4048 if (save != LINK.d)
4050 const(char)* s = (scd.isSharedStaticCtorDeclaration() ? "shared " : "");
4051 deprecation(scd.loc, "`%sstatic` constructor can only be of D linkage", s);
4052 // Just correct it
4053 sc.linkage = LINK.d;
4055 funcDeclarationSemantic(scd);
4056 sc.linkage = save;
4058 // We're going to need ModuleInfo
4059 Module m = scd.getModule();
4060 if (!m)
4061 m = sc._module;
4062 if (m)
4064 m.needmoduleinfo = 1;
4065 //printf("module1 %s needs moduleinfo\n", m.toChars());
4068 foreachUda(scd, sc, (Expression e) {
4069 import dmd.attrib : isEnumAttribute;
4070 if (!isEnumAttribute(e, Id.udaStandalone))
4071 return 0;
4073 if (auto sharedCtor = scd.isSharedStaticCtorDeclaration())
4075 auto trust = sharedCtor.type.isTypeFunction().trust;
4076 if (trust != TRUST.system && trust != TRUST.trusted)
4077 error(e.loc, "a module constructor using `@%s` must be `@system` or `@trusted`", Id.udaStandalone.toChars());
4078 sharedCtor.standalone = true;
4080 else
4081 .error(e.loc, "`@%s` can only be used on shared static constructors", Id.udaStandalone.toChars());
4083 return 1;
4087 override void visit(StaticDtorDeclaration sdd)
4089 if (sdd.semanticRun >= PASS.semanticdone)
4090 return;
4091 if (sdd._scope)
4093 sc = sdd._scope;
4094 sdd._scope = null;
4097 sdd.parent = sc.parent;
4098 Dsymbol p = sdd.parent.pastMixin();
4099 if (!p.isScopeDsymbol())
4101 const(char)* s = (sdd.isSharedStaticDtorDeclaration() ? "shared " : "");
4102 error(sdd.loc, "`%sstatic` destructor can only be member of module/aggregate/template, not %s `%s`", s, p.kind(), p.toChars());
4103 sdd.type = Type.terror;
4104 sdd.errors = true;
4105 return;
4107 if (!sdd.type)
4108 sdd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, sdd.storage_class);
4110 /* If the static ctor appears within a template instantiation,
4111 * it could get called multiple times by the module constructors
4112 * for different modules. Thus, protect it with a gate.
4114 if (sdd.isInstantiated() && sdd.semanticRun < PASS.semantic)
4116 /* Add this prefix to the constructor:
4117 * ```
4118 * static int gate;
4119 * if (--gate != 0) return;
4120 * ```
4121 * or, for shared constructor:
4122 * ```
4123 * shared int gate;
4124 * if (core.atomic.atomicOp!"-="(gate, 1) != 0) return;
4125 * ```
4127 const bool isShared = !!sdd.isSharedStaticDtorDeclaration();
4128 auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
4129 v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
4131 auto sa = new Statements();
4132 Statement s = new ExpStatement(Loc.initial, v);
4133 sa.push(s);
4135 Expression e;
4136 if (isShared)
4138 e = doAtomicOp("-=", v.ident, IntegerExp.literal!(1));
4139 if (e is null)
4141 .error(sdd.loc, "%s `%s` shared static destructo within a template require `core.atomic : atomicOp` to be present", sdd.kind, sdd.toPrettyChars);
4142 return;
4145 else
4147 e = new AddAssignExp(
4148 Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!(-1));
4151 e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!0);
4152 s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
4154 sa.push(s);
4155 if (sdd.fbody)
4156 sa.push(sdd.fbody);
4158 sdd.fbody = new CompoundStatement(Loc.initial, sa);
4160 sdd.vgate = v;
4163 const LINK save = sc.linkage;
4164 if (save != LINK.d)
4166 const(char)* s = (sdd.isSharedStaticDtorDeclaration() ? "shared " : "");
4167 deprecation(sdd.loc, "`%sstatic` destructor can only be of D linkage", s);
4168 // Just correct it
4169 sc.linkage = LINK.d;
4171 funcDeclarationSemantic(sdd);
4172 sc.linkage = save;
4174 // We're going to need ModuleInfo
4175 Module m = sdd.getModule();
4176 if (!m)
4177 m = sc._module;
4178 if (m)
4180 m.needmoduleinfo = 1;
4181 //printf("module2 %s needs moduleinfo\n", m.toChars());
4185 override void visit(InvariantDeclaration invd)
4187 if (invd.semanticRun >= PASS.semanticdone)
4188 return;
4189 if (invd._scope)
4191 sc = invd._scope;
4192 invd._scope = null;
4195 invd.parent = sc.parent;
4196 Dsymbol p = invd.parent.pastMixin();
4197 AggregateDeclaration ad = p.isAggregateDeclaration();
4198 if (!ad)
4200 error(invd.loc, "`invariant` can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
4201 invd.type = Type.terror;
4202 invd.errors = true;
4203 return;
4205 if (invd.ident != Id.classInvariant &&
4206 invd.semanticRun < PASS.semantic &&
4207 !ad.isUnionDeclaration() // users are on their own with union fields
4210 invd.fixupInvariantIdent(ad.invs.length);
4211 ad.invs.push(invd);
4213 if (!invd.type)
4214 invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class);
4216 sc = sc.push();
4217 sc.stc &= ~STC.static_; // not a static invariant
4218 sc.stc |= STC.const_; // invariant() is always const
4219 sc.flags = (sc.flags & ~SCOPE.contract) | SCOPE.invariant_;
4220 sc.linkage = LINK.d;
4222 funcDeclarationSemantic(invd);
4224 sc.pop();
4227 override void visit(UnitTestDeclaration utd)
4229 if (utd.semanticRun >= PASS.semanticdone)
4230 return;
4231 if (utd._scope)
4233 sc = utd._scope;
4234 utd._scope = null;
4237 utd.visibility = sc.visibility;
4239 utd.parent = sc.parent;
4240 Dsymbol p = utd.parent.pastMixin();
4241 if (!p.isScopeDsymbol())
4243 error(utd.loc, "`unittest` can only be a member of module/aggregate/template, not %s `%s`", p.kind(), p.toChars());
4244 utd.type = Type.terror;
4245 utd.errors = true;
4246 return;
4249 if (global.params.useUnitTests)
4251 if (!utd.type)
4252 utd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, utd.storage_class);
4253 Scope* sc2 = sc.push();
4254 sc2.linkage = LINK.d;
4255 funcDeclarationSemantic(utd);
4256 sc2.pop();
4259 version (none)
4261 // We're going to need ModuleInfo even if the unit tests are not
4262 // compiled in, because other modules may import this module and refer
4263 // to this ModuleInfo.
4264 // (This doesn't make sense to me?)
4265 Module m = utd.getModule();
4266 if (!m)
4267 m = sc._module;
4268 if (m)
4270 //printf("module3 %s needs moduleinfo\n", m.toChars());
4271 m.needmoduleinfo = 1;
4276 override void visit(NewDeclaration nd)
4278 //printf("NewDeclaration::semantic()\n");
4279 if (nd.semanticRun >= PASS.semanticdone)
4280 return;
4281 if (!nd.type)
4282 nd.type = new TypeFunction(ParameterList(), Type.tvoid.pointerTo(), LINK.d, nd.storage_class);
4284 funcDeclarationSemantic(nd);
4287 override void visit(StructDeclaration sd)
4289 enum log = false;
4290 if (log) printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4292 //static int count; if (++count == 20) assert(0);
4294 if (sd.semanticRun >= PASS.semanticdone)
4295 return;
4296 int errors = global.errors;
4298 //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4299 Scope* scx = null;
4300 if (sd._scope)
4302 sc = sd._scope;
4303 scx = sd._scope; // save so we don't make redundant copies
4304 sd._scope = null;
4307 if (!sd.parent)
4309 assert(sc.parent && sc.func);
4310 sd.parent = sc.parent;
4312 assert(sd.parent && !sd.isAnonymous());
4314 if (sd.errors)
4315 sd.type = Type.terror;
4316 if (sd.semanticRun == PASS.initial)
4317 sd.type = sd.type.addSTC(sc.stc | sd.storage_class);
4318 sd.type = sd.type.typeSemantic(sd.loc, sc);
4319 auto ts = sd.type.isTypeStruct();
4320 if (ts)
4322 if (ts.sym != sd)
4324 TemplateInstance ti = ts.sym.isInstantiated();
4325 if (ti && isError(ti))
4326 ts.sym = sd;
4327 /* For C modules, if module A contains `struct S;` and
4328 * module B contains `struct S { members...}` then replace
4329 * the former with the latter
4331 else if (!ts.sym.members && sd.members)
4332 ts.sym = sd;
4336 // Ungag errors when not speculative
4337 Ungag ungag = sd.ungagSpeculative();
4339 if (sd.semanticRun == PASS.initial)
4341 sd.visibility = sc.visibility;
4343 if (sd.alignment.isUnknown()) // can be set already by `struct __declspec(align(N)) Tag { ... }`
4344 sd.alignment = sc.alignment();
4346 sd.storage_class |= sc.stc;
4347 if (sd.storage_class & STC.abstract_)
4348 .error(sd.loc, "%s `%s` structs, unions cannot be `abstract`", sd.kind, sd.toPrettyChars);
4350 sd.userAttribDecl = sc.userAttribDecl;
4352 if (sc.linkage == LINK.cpp)
4353 sd.classKind = ClassKind.cpp;
4354 else if (sc.linkage == LINK.c)
4355 sd.classKind = ClassKind.c;
4356 sd.cppnamespace = sc.namespace;
4357 sd.cppmangle = sc.cppmangle;
4359 else if (sd.symtab && !scx)
4360 return;
4362 sd.semanticRun = PASS.semantic;
4363 UserAttributeDeclaration.checkGNUABITag(sd, sc.linkage);
4365 if (!sd.members) // if opaque declaration
4367 if (log) printf("\topaque declaration %s\n", sd.toChars());
4368 sd.semanticRun = PASS.semanticdone;
4369 return;
4371 if (!sd.symtab)
4373 sd.symtab = new DsymbolTable();
4375 sd.members.foreachDsymbol( s => s.addMember(sc, sd) );
4378 auto sc2 = sd.newScope(sc);
4380 /* Set scope so if there are forward references, we still might be able to
4381 * resolve individual members like enums.
4383 sd.members.foreachDsymbol( s => s.setScope(sc2) );
4384 sd.members.foreachDsymbol( s => s.importAll(sc2) );
4385 sd.members.foreachDsymbol( (s) { s.dsymbolSemantic(sc2); sd.errors |= s.errors; } );
4387 if (sd.errors)
4388 sd.type = Type.terror;
4390 if (!sd.determineFields())
4392 if (sd.type.ty != Terror)
4394 .error(sd.loc, "%s `%s` circular or forward reference", sd.kind, sd.toPrettyChars);
4395 sd.errors = true;
4396 sd.type = Type.terror;
4399 sc2.pop();
4400 sd.semanticRun = PASS.semanticdone;
4401 return;
4403 /* Following special member functions creation needs semantic analysis
4404 * completion of sub-structs in each field types. For example, buildDtor
4405 * needs to check existence of elaborate dtor in type of each fields.
4406 * See the case in compilable/test14838.d
4408 foreach (v; sd.fields)
4410 Type tb = v.type.baseElemOf();
4411 if (tb.ty != Tstruct)
4412 continue;
4413 auto sdec = (cast(TypeStruct)tb).sym;
4414 if (sdec.semanticRun >= PASS.semanticdone)
4415 continue;
4417 sc2.pop();
4419 if (log) printf("\tdeferring %s\n", sd.toChars());
4420 return deferDsymbolSemantic(sc, sd, scx);
4423 /* Look for special member functions.
4425 sd.disableNew = sd.search(Loc.initial, Id.classNew) !is null;
4427 // Look for the constructor
4428 sd.ctor = sd.searchCtor();
4430 buildDtors(sd, sc2);
4432 sd.hasCopyCtor = buildCopyCtor(sd, sc2);
4433 sd.postblit = buildPostBlit(sd, sc2);
4435 buildOpAssign(sd, sc2);
4436 buildOpEquals(sd, sc2);
4438 if (!(sc2.flags & SCOPE.Cfile) &&
4439 global.params.useTypeInfo && Type.dtypeinfo) // these functions are used for TypeInfo
4441 sd.xeq = buildXopEquals(sd, sc2);
4442 sd.xcmp = buildXopCmp(sd, sc2);
4443 sd.xhash = buildXtoHash(sd, sc2);
4446 sd.inv = buildInv(sd, sc2);
4448 sd.semanticRun = PASS.semanticdone;
4449 if (log) printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4451 sc2.pop();
4453 if (sd.ctor)
4455 Dsymbol scall = sd.search(Loc.initial, Id.call);
4456 if (scall)
4458 uint xerrors = global.startGagging();
4459 sc = sc.push();
4460 sc.tinst = null;
4461 sc.minst = null;
4462 auto fcall = resolveFuncCall(sd.loc, sc, scall, null, null, ArgumentList(), FuncResolveFlag.quiet);
4463 sc = sc.pop();
4464 global.endGagging(xerrors);
4466 if (fcall && fcall.isStatic())
4468 .error(fcall.loc, "%s `%s` `static opCall` is hidden by constructors and can never be called", sd.kind, sd.toPrettyChars);
4469 errorSupplemental(fcall.loc, "Please use a factory method instead, or replace all constructors with `static opCall`.");
4474 if (ts && ts.sym != sd)
4476 StructDeclaration sym = ts.sym;
4477 if (sd.isCsymbol() && sym.isCsymbol())
4479 /* This is two structs imported from different C files.
4480 * Just ignore sd, the second one. The first one will always
4481 * be found when going through the type.
4484 else
4486 version (none)
4488 printf("this = %p %s\n", sd, sd.toChars());
4489 printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars());
4491 // https://issues.dlang.org/show_bug.cgi?id=19024
4492 .error(sd.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", sd.kind, sd.toPrettyChars, sym.loc.toChars());
4496 if (global.errors != errors)
4498 // The type is no good.
4499 sd.type = Type.terror;
4500 sd.errors = true;
4501 if (sd.deferred)
4502 sd.deferred.errors = true;
4505 if (sd.deferred && !global.gag)
4507 sd.deferred.semantic2(sc);
4508 sd.deferred.semantic3(sc);
4511 version (none)
4513 // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
4514 // Deprecated in 2.100
4515 // Make an error in 2.110
4516 if (sd.storage_class & STC.scope_)
4517 deprecation(sd.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
4519 //printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
4522 void interfaceSemantic(ClassDeclaration cd)
4524 cd.vtblInterfaces = new BaseClasses();
4525 cd.vtblInterfaces.reserve(cd.interfaces.length);
4526 foreach (b; cd.interfaces)
4528 cd.vtblInterfaces.push(b);
4529 b.copyBaseInterfaces(cd.vtblInterfaces);
4533 override void visit(ClassDeclaration cldec)
4535 //printf("ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", cldec.toChars(), cldec.type, cldec.sizeok, this);
4536 //printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : "");
4537 //printf("sc.stc = %x\n", sc.stc);
4539 //{ static int n; if (++n == 20) *(char*)0=0; }
4541 if (cldec.semanticRun >= PASS.semanticdone)
4542 return;
4543 int errors = global.errors;
4545 //printf("+ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
4547 Scope* scx = null;
4548 if (cldec._scope)
4550 sc = cldec._scope;
4551 scx = cldec._scope; // save so we don't make redundant copies
4552 cldec._scope = null;
4555 if (!cldec.parent)
4557 assert(sc.parent);
4558 cldec.parent = sc.parent;
4561 if (cldec.errors)
4562 cldec.type = Type.terror;
4563 if (cldec.semanticRun == PASS.initial)
4564 cldec.type = cldec.type.addSTC(sc.stc | cldec.storage_class);
4565 cldec.type = cldec.type.typeSemantic(cldec.loc, sc);
4566 if (auto tc = cldec.type.isTypeClass())
4567 if (tc.sym != cldec)
4569 auto ti = tc.sym.isInstantiated();
4570 if (ti && isError(ti))
4571 tc.sym = cldec;
4574 // Ungag errors when not speculative
4575 Ungag ungag = cldec.ungagSpeculative();
4577 if (cldec.semanticRun == PASS.initial)
4579 cldec.visibility = sc.visibility;
4581 cldec.storage_class |= sc.stc;
4582 if (cldec.storage_class & STC.auto_)
4583 .error(cldec.loc, "%s `%s` storage class `auto` is invalid when declaring a class, did you mean to use `scope`?", cldec.kind, cldec.toPrettyChars);
4584 if (cldec.storage_class & STC.scope_)
4585 cldec.stack = true;
4586 if (cldec.storage_class & STC.abstract_)
4587 cldec.isabstract = ThreeState.yes;
4589 cldec.userAttribDecl = sc.userAttribDecl;
4591 if (sc.linkage == LINK.cpp)
4592 cldec.classKind = ClassKind.cpp;
4593 cldec.cppnamespace = sc.namespace;
4594 cldec.cppmangle = sc.cppmangle;
4595 if (sc.linkage == LINK.objc)
4596 objc.setObjc(cldec);
4598 else if (cldec.symtab && !scx)
4600 return;
4602 cldec.semanticRun = PASS.semantic;
4603 UserAttributeDeclaration.checkGNUABITag(cldec, sc.linkage);
4604 checkMustUseReserved(cldec);
4606 if (cldec.baseok < Baseok.done)
4608 /* https://issues.dlang.org/show_bug.cgi?id=12078
4609 * https://issues.dlang.org/show_bug.cgi?id=12143
4610 * https://issues.dlang.org/show_bug.cgi?id=15733
4611 * While resolving base classes and interfaces, a base may refer
4612 * the member of this derived class. In that time, if all bases of
4613 * this class can be determined, we can go forward the semantc process
4614 * beyond the Lancestorsdone. To do the recursive semantic analysis,
4615 * temporarily set and unset `_scope` around exp().
4617 T resolveBase(T)(lazy T exp)
4619 if (!scx)
4621 scx = sc.copy();
4622 scx.setNoFree();
4624 static if (!is(T == void))
4626 cldec._scope = scx;
4627 auto r = exp();
4628 cldec._scope = null;
4629 return r;
4631 else
4633 cldec._scope = scx;
4634 exp();
4635 cldec._scope = null;
4639 cldec.baseok = Baseok.start;
4641 // Expand any tuples in baseclasses[]
4642 for (size_t i = 0; i < cldec.baseclasses.length;)
4644 auto b = (*cldec.baseclasses)[i];
4645 b.type = resolveBase(b.type.typeSemantic(cldec.loc, sc));
4647 Type tb = b.type.toBasetype();
4648 if (auto tup = tb.isTypeTuple())
4650 cldec.baseclasses.remove(i);
4651 size_t dim = Parameter.dim(tup.arguments);
4652 for (size_t j = 0; j < dim; j++)
4654 Parameter arg = Parameter.getNth(tup.arguments, j);
4655 b = new BaseClass(arg.type);
4656 cldec.baseclasses.insert(i + j, b);
4659 else
4660 i++;
4663 if (cldec.baseok >= Baseok.done)
4665 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
4666 if (cldec.semanticRun >= PASS.semanticdone)
4667 return;
4668 goto Lancestorsdone;
4671 // See if there's a base class as first in baseclasses[]
4672 if (cldec.baseclasses.length)
4674 BaseClass* b = (*cldec.baseclasses)[0];
4675 Type tb = b.type.toBasetype();
4676 TypeClass tc = tb.isTypeClass();
4677 if (!tc)
4679 if (b.type != Type.terror)
4680 .error(cldec.loc, "%s `%s` base type must be `class` or `interface`, not `%s`", cldec.kind, cldec.toPrettyChars, b.type.toChars());
4681 cldec.baseclasses.remove(0);
4682 goto L7;
4684 if (tc.sym.isDeprecated())
4686 if (!cldec.isDeprecated())
4688 // Deriving from deprecated class makes this one deprecated too
4689 cldec.setDeprecated();
4690 tc.checkDeprecated(cldec.loc, sc);
4693 if (tc.sym.isInterfaceDeclaration())
4694 goto L7;
4696 for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass)
4698 if (cdb == cldec)
4700 .error(cldec.loc, "%s `%s` circular inheritance", cldec.kind, cldec.toPrettyChars);
4701 cldec.baseclasses.remove(0);
4702 goto L7;
4706 /* https://issues.dlang.org/show_bug.cgi?id=11034
4707 * Class inheritance hierarchy
4708 * and instance size of each classes are orthogonal information.
4709 * Therefore, even if tc.sym.sizeof == Sizeok.none,
4710 * we need to set baseClass field for class covariance check.
4712 cldec.baseClass = tc.sym;
4713 b.sym = cldec.baseClass;
4715 if (tc.sym.baseok < Baseok.done)
4716 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
4717 if (tc.sym.baseok < Baseok.done)
4719 //printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars());
4720 if (tc.sym._scope)
4721 Module.addDeferredSemantic(tc.sym);
4722 cldec.baseok = Baseok.none;
4727 // Treat the remaining entries in baseclasses as interfaces
4728 // Check for errors, handle forward references
4729 int multiClassError = cldec.baseClass is null ? 0 : 1;
4731 BCLoop:
4732 for (size_t i = (cldec.baseClass ? 1 : 0); i < cldec.baseclasses.length;)
4734 BaseClass* b = (*cldec.baseclasses)[i];
4735 Type tb = b.type.toBasetype();
4736 TypeClass tc = tb.isTypeClass();
4737 if (!tc || !tc.sym.isInterfaceDeclaration())
4739 // It's a class
4740 if (tc)
4742 if (multiClassError == 0)
4744 .error(cldec.loc,"`%s`: base class must be specified first, " ~
4745 "before any interfaces.", cldec.toPrettyChars());
4746 multiClassError += 1;
4748 else if (multiClassError >= 1)
4750 if(multiClassError == 1)
4751 .error(cldec.loc, "`%s`: multiple class inheritance is not supported." ~
4752 " Use multiple interface inheritance and/or composition.", cldec.toPrettyChars());
4753 multiClassError += 1;
4755 if (tc.sym.fields.length)
4756 errorSupplemental(cldec.loc,"`%s` has fields, consider making it a member of `%s`",
4757 b.type.toChars(), cldec.type.toChars());
4758 else
4759 errorSupplemental(cldec.loc,"`%s` has no fields, consider making it an `interface`",
4760 b.type.toChars());
4763 // It's something else: e.g. `int` in `class Foo : Bar, int { ... }`
4764 else if (b.type != Type.terror)
4766 error(cldec.loc,"`%s`: base type must be `interface`, not `%s`",
4767 cldec.toPrettyChars(), b.type.toChars());
4769 cldec.baseclasses.remove(i);
4770 continue;
4773 // Check for duplicate interfaces
4774 for (size_t j = (cldec.baseClass ? 1 : 0); j < i; j++)
4776 BaseClass* b2 = (*cldec.baseclasses)[j];
4777 if (b2.sym == tc.sym)
4779 .error(cldec.loc, "%s `%s` inherits from duplicate interface `%s`", cldec.kind, cldec.toPrettyChars, b2.sym.toChars());
4780 cldec.baseclasses.remove(i);
4781 continue BCLoop;
4784 if (tc.sym.isDeprecated())
4786 if (!cldec.isDeprecated())
4788 // Deriving from deprecated class makes this one deprecated too
4789 cldec.setDeprecated();
4790 tc.checkDeprecated(cldec.loc, sc);
4794 b.sym = tc.sym;
4796 if (tc.sym.baseok < Baseok.done)
4797 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
4798 if (tc.sym.baseok < Baseok.done)
4800 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
4801 if (tc.sym._scope)
4802 Module.addDeferredSemantic(tc.sym);
4803 cldec.baseok = Baseok.none;
4805 i++;
4807 if (cldec.baseok == Baseok.none)
4809 // Forward referencee of one or more bases, try again later
4810 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
4811 return deferDsymbolSemantic(sc, cldec, scx);
4813 cldec.baseok = Baseok.done;
4815 if (cldec.classKind == ClassKind.objc || (cldec.baseClass && cldec.baseClass.classKind == ClassKind.objc))
4816 cldec.classKind = ClassKind.objc; // Objective-C classes do not inherit from Object
4818 // If no base class, and this is not an Object, use Object as base class
4819 if (!cldec.baseClass && cldec.ident != Id.Object && cldec.object && cldec.classKind == ClassKind.d)
4821 void badObjectDotD()
4823 .error(cldec.loc, "%s `%s` missing or corrupt object.d", cldec.kind, cldec.toPrettyChars);
4824 fatal();
4827 if (!cldec.object || cldec.object.errors)
4828 badObjectDotD();
4830 Type t = cldec.object.type;
4831 t = t.typeSemantic(cldec.loc, sc).toBasetype();
4832 if (t.ty == Terror)
4833 badObjectDotD();
4834 TypeClass tc = t.isTypeClass();
4835 assert(tc);
4837 auto b = new BaseClass(tc);
4838 cldec.baseclasses.shift(b);
4840 cldec.baseClass = tc.sym;
4841 assert(!cldec.baseClass.isInterfaceDeclaration());
4842 b.sym = cldec.baseClass;
4844 if (cldec.baseClass)
4846 if (cldec.baseClass.storage_class & STC.final_)
4847 .error(cldec.loc, "%s `%s` cannot inherit from class `%s` because it is `final`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
4849 // Inherit properties from base class
4850 if (cldec.baseClass.isCOMclass())
4851 cldec.com = true;
4852 if (cldec.baseClass.isCPPclass())
4853 cldec.classKind = ClassKind.cpp;
4854 if (cldec.classKind != cldec.baseClass.classKind)
4855 .error(cldec.loc, "%s `%s` with %s linkage cannot inherit from class `%s` with %s linkage", cldec.kind, cldec.toPrettyChars,
4856 ClassKindToChars(cldec.classKind), cldec.baseClass.toChars(), ClassKindToChars(cldec.baseClass.classKind));
4858 if (cldec.baseClass.stack)
4859 cldec.stack = true;
4860 cldec.enclosing = cldec.baseClass.enclosing;
4861 cldec.storage_class |= cldec.baseClass.storage_class & STC.TYPECTOR;
4864 cldec.interfaces = cldec.baseclasses.tdata()[(cldec.baseClass ? 1 : 0) .. cldec.baseclasses.length];
4865 foreach (b; cldec.interfaces)
4867 // If this is an interface, and it derives from a COM interface,
4868 // then this is a COM interface too.
4869 if (b.sym.isCOMinterface())
4870 cldec.com = true;
4871 if (cldec.classKind == ClassKind.cpp && !b.sym.isCPPinterface())
4873 .error(cldec.loc, "C++ class `%s` cannot implement D interface `%s`",
4874 cldec.toPrettyChars(), b.sym.toPrettyChars());
4877 interfaceSemantic(cldec);
4879 Lancestorsdone:
4880 //printf("\tClassDeclaration.dsymbolSemantic(%s) baseok = %d\n", toChars(), baseok);
4882 if (!cldec.members) // if opaque declaration
4884 cldec.semanticRun = PASS.semanticdone;
4885 return;
4887 if (!cldec.symtab)
4889 cldec.symtab = new DsymbolTable();
4891 /* https://issues.dlang.org/show_bug.cgi?id=12152
4892 * The semantic analysis of base classes should be finished
4893 * before the members semantic analysis of this class, in order to determine
4894 * vtbl in this class. However if a base class refers the member of this class,
4895 * it can be resolved as a normal forward reference.
4896 * Call addMember() and setScope() to make this class members visible from the base classes.
4898 cldec.members.foreachDsymbol( s => s.addMember(sc, cldec) );
4900 auto sc2 = cldec.newScope(sc);
4902 /* Set scope so if there are forward references, we still might be able to
4903 * resolve individual members like enums.
4905 cldec.members.foreachDsymbol( s => s.setScope(sc2) );
4907 sc2.pop();
4910 for (size_t i = 0; i < cldec.baseclasses.length; i++)
4912 BaseClass* b = (*cldec.baseclasses)[i];
4913 Type tb = b.type.toBasetype();
4914 TypeClass tc = tb.isTypeClass();
4915 if (tc.sym.semanticRun < PASS.semanticdone)
4917 // Forward referencee of one or more bases, try again later
4918 if (tc.sym._scope)
4919 Module.addDeferredSemantic(tc.sym);
4920 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
4921 return deferDsymbolSemantic(sc, cldec, scx);
4925 if (cldec.baseok == Baseok.done)
4927 cldec.baseok = Baseok.semanticdone;
4928 objc.setMetaclass(cldec, sc);
4930 // initialize vtbl
4931 if (cldec.baseClass)
4933 if (cldec.classKind == ClassKind.cpp && cldec.baseClass.vtbl.length == 0)
4935 .error(cldec.loc, "%s `%s` C++ base class `%s` needs at least one virtual function", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
4938 // Copy vtbl[] from base class
4939 assert(cldec.vtbl.length == 0);
4940 cldec.vtbl.setDim(cldec.baseClass.vtbl.length);
4941 memcpy(cldec.vtbl.tdata(), cldec.baseClass.vtbl.tdata(), (void*).sizeof * cldec.vtbl.length);
4943 cldec.vthis = cldec.baseClass.vthis;
4944 cldec.vthis2 = cldec.baseClass.vthis2;
4946 else
4948 // No base class, so this is the root of the class hierarchy
4949 cldec.vtbl.setDim(0);
4950 if (cldec.vtblOffset())
4951 cldec.vtbl.push(cldec); // leave room for classinfo as first member
4954 /* If this is a nested class, add the hidden 'this'
4955 * member which is a pointer to the enclosing scope.
4957 if (cldec.vthis) // if inheriting from nested class
4959 // Use the base class's 'this' member
4960 if (cldec.storage_class & STC.static_)
4961 .error(cldec.loc, "%s `%s` static class cannot inherit from nested class `%s`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
4962 if (cldec.toParentLocal() != cldec.baseClass.toParentLocal() &&
4963 (!cldec.toParentLocal() ||
4964 !cldec.baseClass.toParentLocal().getType() ||
4965 !cldec.baseClass.toParentLocal().getType().isBaseOf(cldec.toParentLocal().getType(), null)))
4967 if (cldec.toParentLocal())
4969 .error(cldec.loc, "%s `%s` is nested within `%s`, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
4970 cldec.toParentLocal().toChars(),
4971 cldec.baseClass.toChars(),
4972 cldec.baseClass.toParentLocal().toChars());
4974 else
4976 .error(cldec.loc, "%s `%s` is not nested, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
4977 cldec.baseClass.toChars(),
4978 cldec.baseClass.toParentLocal().toChars());
4981 if (cldec.vthis2)
4983 if (cldec.toParent2() != cldec.baseClass.toParent2() &&
4984 (!cldec.toParent2() ||
4985 !cldec.baseClass.toParent2().getType() ||
4986 !cldec.baseClass.toParent2().getType().isBaseOf(cldec.toParent2().getType(), null)))
4988 if (cldec.toParent2() && cldec.toParent2() != cldec.toParentLocal())
4990 .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,
4991 cldec.toParent2().toChars(),
4992 cldec.baseClass.toChars(),
4993 cldec.baseClass.toParent2().toChars());
4995 else
4997 .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,
4998 cldec.baseClass.toChars(),
4999 cldec.baseClass.toParent2().toChars());
5003 else
5004 cldec.makeNested2();
5006 else
5007 cldec.makeNested();
5010 auto sc2 = cldec.newScope(sc);
5012 cldec.members.foreachDsymbol( s => s.importAll(sc2) );
5014 // Note that members.length can grow due to tuple expansion during semantic()
5015 cldec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
5017 if (!cldec.determineFields())
5019 assert(cldec.type == Type.terror);
5020 sc2.pop();
5021 return;
5023 /* Following special member functions creation needs semantic analysis
5024 * completion of sub-structs in each field types.
5026 foreach (v; cldec.fields)
5028 Type tb = v.type.baseElemOf();
5029 if (tb.ty != Tstruct)
5030 continue;
5031 auto sd = (cast(TypeStruct)tb).sym;
5032 if (sd.semanticRun >= PASS.semanticdone)
5033 continue;
5035 sc2.pop();
5037 //printf("\tdeferring %s\n", toChars());
5038 return deferDsymbolSemantic(sc, cldec, scx);
5041 /* Look for special member functions.
5042 * They must be in this class, not in a base class.
5044 // Can be in base class
5045 cldec.disableNew = cldec.search(Loc.initial, Id.classNew) !is null;
5047 // Look for the constructor
5048 cldec.ctor = cldec.searchCtor();
5050 if (!cldec.ctor && cldec.noDefaultCtor)
5052 // A class object is always created by constructor, so this check is legitimate.
5053 foreach (v; cldec.fields)
5055 if (v.storage_class & STC.nodefaultctor)
5056 error(v.loc, "field `%s` must be initialized in constructor", v.toChars());
5060 // If this class has no constructor, but base class has a default
5061 // ctor, create a constructor:
5062 // this() { }
5063 if (!cldec.ctor && cldec.baseClass && cldec.baseClass.ctor)
5065 auto fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type, ArgumentList(), FuncResolveFlag.quiet);
5066 if (!fd) // try shared base ctor instead
5067 fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type.sharedOf, ArgumentList(), FuncResolveFlag.quiet);
5068 if (fd && !fd.errors)
5070 //printf("Creating default this(){} for class %s\n", toChars());
5071 auto btf = fd.type.toTypeFunction();
5072 auto tf = new TypeFunction(ParameterList(), null, LINK.d, fd.storage_class);
5073 tf.mod = btf.mod;
5074 // Don't copy @safe, ... from the base class constructor and let it be inferred instead
5075 // This is required if other lowerings add code to the generated constructor which
5076 // is less strict (e.g. `preview=dtorfields` might introduce a call to a less qualified dtor)
5078 auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf);
5079 ctor.storage_class |= STC.inference | (fd.storage_class & STC.scope_);
5080 ctor.isGenerated = true;
5081 ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
5083 cldec.members.push(ctor);
5084 ctor.addMember(sc, cldec);
5085 ctor.dsymbolSemantic(sc2);
5087 cldec.ctor = ctor;
5088 cldec.defaultCtor = ctor;
5090 else
5092 .error(cldec.loc, "%s `%s` cannot implicitly generate a default constructor when base class `%s` is missing a default constructor", cldec.kind, cldec.toPrettyChars,
5093 cldec.baseClass.toPrettyChars());
5097 buildDtors(cldec, sc2);
5099 if (cldec.classKind == ClassKind.cpp && cldec.cppDtorVtblIndex != -1)
5101 // now we've built the aggregate destructor, we'll make it virtual and assign it to the reserved vtable slot
5102 cldec.dtor.vtblIndex = cldec.cppDtorVtblIndex;
5103 cldec.vtbl[cldec.cppDtorVtblIndex] = cldec.dtor;
5105 if (target.cpp.twoDtorInVtable)
5107 // TODO: create a C++ compatible deleting destructor (call out to `operator delete`)
5108 // for the moment, we'll call the non-deleting destructor and leak
5109 cldec.vtbl[cldec.cppDtorVtblIndex + 1] = cldec.dtor;
5113 if (auto f = hasIdentityOpAssign(cldec, sc2))
5115 if (!(f.storage_class & STC.disable))
5116 .error(f.loc, "%s `%s` identity assignment operator overload is illegal", cldec.kind, cldec.toPrettyChars);
5119 cldec.inv = buildInv(cldec, sc2);
5121 cldec.semanticRun = PASS.semanticdone;
5122 //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5124 sc2.pop();
5126 /* isAbstract() is undecidable in some cases because of circular dependencies.
5127 * Now that semantic is finished, get a definitive result, and error if it is not the same.
5129 if (cldec.isabstract != ThreeState.none) // if evaluated it before completion
5131 const isabstractsave = cldec.isabstract;
5132 cldec.isabstract = ThreeState.none;
5133 cldec.isAbstract(); // recalculate
5134 if (cldec.isabstract != isabstractsave)
5136 .error(cldec.loc, "%s `%s` cannot infer `abstract` attribute due to circular dependencies", cldec.kind, cldec.toPrettyChars);
5140 if (cldec.type.ty == Tclass && (cast(TypeClass)cldec.type).sym != cldec)
5142 // https://issues.dlang.org/show_bug.cgi?id=17492
5143 ClassDeclaration cd = (cast(TypeClass)cldec.type).sym;
5144 version (none)
5146 printf("this = %p %s\n", cldec, cldec.toPrettyChars());
5147 printf("type = %d sym = %p, %s\n", cldec.type.ty, cd, cd.toPrettyChars());
5149 .error(cldec.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", cldec.kind, cldec.toPrettyChars, cd.loc.toChars());
5152 if (global.errors != errors || (cldec.baseClass && cldec.baseClass.errors))
5154 // The type is no good, but we should keep the
5155 // the type so that we have more accurate error messages
5156 // See: https://issues.dlang.org/show_bug.cgi?id=23552
5157 cldec.errors = true;
5158 if (cldec.deferred)
5159 cldec.deferred.errors = true;
5162 // Verify fields of a synchronized class are not public
5163 if (cldec.storage_class & STC.synchronized_)
5165 foreach (vd; cldec.fields)
5167 if (!vd.isThisDeclaration() &&
5168 vd.visible() >= Visibility(Visibility.Kind.public_))
5170 .error(vd.loc, "%s `%s` Field members of a `synchronized` class cannot be `%s`", vd.kind, vd.toPrettyChars,
5171 visibilityToChars(vd.visible().kind));
5176 if (cldec.deferred && !global.gag)
5178 cldec.deferred.semantic2(sc);
5179 cldec.deferred.semantic3(sc);
5181 //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
5183 version (none)
5185 // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
5186 // Deprecated in 2.100
5187 // Make an error in 2.110
5188 // Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
5189 if (cldec.storage_class & STC.scope_)
5190 deprecation(cldec.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
5194 override void visit(InterfaceDeclaration idec)
5196 /// Returns: `true` is this is an anonymous Objective-C metaclass
5197 static bool isAnonymousMetaclass(InterfaceDeclaration idec)
5199 return idec.classKind == ClassKind.objc &&
5200 idec.objc.isMeta &&
5201 idec.isAnonymous;
5204 //printf("InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5205 if (idec.semanticRun >= PASS.semanticdone)
5206 return;
5207 int errors = global.errors;
5209 //printf("+InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5211 Scope* scx = null;
5212 if (idec._scope)
5214 sc = idec._scope;
5215 scx = idec._scope; // save so we don't make redundant copies
5216 idec._scope = null;
5219 if (!idec.parent)
5221 assert(sc.parent && sc.func);
5222 idec.parent = sc.parent;
5224 // Objective-C metaclasses are anonymous
5225 assert(idec.parent && !idec.isAnonymous || isAnonymousMetaclass(idec));
5227 if (idec.errors)
5228 idec.type = Type.terror;
5229 idec.type = idec.type.typeSemantic(idec.loc, sc);
5230 if (idec.type.ty == Tclass && (cast(TypeClass)idec.type).sym != idec)
5232 auto ti = (cast(TypeClass)idec.type).sym.isInstantiated();
5233 if (ti && isError(ti))
5234 (cast(TypeClass)idec.type).sym = idec;
5237 // Ungag errors when not speculative
5238 Ungag ungag = idec.ungagSpeculative();
5240 if (idec.semanticRun == PASS.initial)
5242 idec.visibility = sc.visibility;
5244 idec.storage_class |= sc.stc;
5245 idec.userAttribDecl = sc.userAttribDecl;
5247 else if (idec.symtab)
5249 if (idec.sizeok == Sizeok.done || !scx)
5251 idec.semanticRun = PASS.semanticdone;
5252 return;
5255 idec.semanticRun = PASS.semantic;
5257 if (idec.baseok < Baseok.done)
5259 T resolveBase(T)(lazy T exp)
5261 if (!scx)
5263 scx = sc.copy();
5264 scx.setNoFree();
5266 static if (!is(T == void))
5268 idec._scope = scx;
5269 auto r = exp();
5270 idec._scope = null;
5271 return r;
5273 else
5275 idec._scope = scx;
5276 exp();
5277 idec._scope = null;
5281 idec.baseok = Baseok.start;
5283 // Expand any tuples in baseclasses[]
5284 for (size_t i = 0; i < idec.baseclasses.length;)
5286 auto b = (*idec.baseclasses)[i];
5287 b.type = resolveBase(b.type.typeSemantic(idec.loc, sc));
5289 Type tb = b.type.toBasetype();
5290 if (auto tup = tb.isTypeTuple())
5292 idec.baseclasses.remove(i);
5293 size_t dim = Parameter.dim(tup.arguments);
5294 for (size_t j = 0; j < dim; j++)
5296 Parameter arg = Parameter.getNth(tup.arguments, j);
5297 b = new BaseClass(arg.type);
5298 idec.baseclasses.insert(i + j, b);
5301 else
5302 i++;
5305 if (idec.baseok >= Baseok.done)
5307 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
5308 if (idec.semanticRun >= PASS.semanticdone)
5309 return;
5310 goto Lancestorsdone;
5313 if (!idec.baseclasses.length && sc.linkage == LINK.cpp)
5314 idec.classKind = ClassKind.cpp;
5315 idec.cppnamespace = sc.namespace;
5316 UserAttributeDeclaration.checkGNUABITag(idec, sc.linkage);
5317 checkMustUseReserved(idec);
5319 if (sc.linkage == LINK.objc)
5320 objc.setObjc(idec);
5322 // Check for errors, handle forward references
5323 BCLoop:
5324 for (size_t i = 0; i < idec.baseclasses.length;)
5326 BaseClass* b = (*idec.baseclasses)[i];
5327 Type tb = b.type.toBasetype();
5328 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null;
5329 if (!tc || !tc.sym.isInterfaceDeclaration())
5331 if (b.type != Type.terror)
5332 .error(idec.loc, "%s `%s` base type must be `interface`, not `%s`", idec.kind, idec.toPrettyChars, b.type.toChars());
5333 idec.baseclasses.remove(i);
5334 continue;
5337 // Check for duplicate interfaces
5338 for (size_t j = 0; j < i; j++)
5340 BaseClass* b2 = (*idec.baseclasses)[j];
5341 if (b2.sym == tc.sym)
5343 .error(idec.loc, "%s `%s` inherits from duplicate interface `%s`", idec.kind, idec.toPrettyChars, b2.sym.toChars());
5344 idec.baseclasses.remove(i);
5345 continue BCLoop;
5348 if (tc.sym == idec || idec.isBaseOf2(tc.sym))
5350 .error(idec.loc, "%s `%s` circular inheritance of interface", idec.kind, idec.toPrettyChars);
5351 idec.baseclasses.remove(i);
5352 continue;
5354 if (tc.sym.isDeprecated())
5356 if (!idec.isDeprecated())
5358 // Deriving from deprecated interface makes this one deprecated too
5359 idec.setDeprecated();
5360 tc.checkDeprecated(idec.loc, sc);
5364 b.sym = tc.sym;
5366 if (tc.sym.baseok < Baseok.done)
5367 resolveBase(tc.sym.dsymbolSemantic(null)); // Try to resolve forward reference
5368 if (tc.sym.baseok < Baseok.done)
5370 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
5371 if (tc.sym._scope)
5372 Module.addDeferredSemantic(tc.sym);
5373 idec.baseok = Baseok.none;
5375 i++;
5377 if (idec.baseok == Baseok.none)
5379 // Forward referencee of one or more bases, try again later
5380 return deferDsymbolSemantic(sc, idec, scx);
5382 idec.baseok = Baseok.done;
5384 idec.interfaces = idec.baseclasses.tdata()[0 .. idec.baseclasses.length];
5385 foreach (b; idec.interfaces)
5387 // If this is an interface, and it derives from a COM interface,
5388 // then this is a COM interface too.
5389 if (b.sym.isCOMinterface())
5390 idec.com = true;
5391 if (b.sym.isCPPinterface())
5392 idec.classKind = ClassKind.cpp;
5395 interfaceSemantic(idec);
5397 Lancestorsdone:
5399 if (!idec.members) // if opaque declaration
5401 idec.semanticRun = PASS.semanticdone;
5402 return;
5404 if (!idec.symtab)
5405 idec.symtab = new DsymbolTable();
5407 for (size_t i = 0; i < idec.baseclasses.length; i++)
5409 BaseClass* b = (*idec.baseclasses)[i];
5410 Type tb = b.type.toBasetype();
5411 TypeClass tc = tb.isTypeClass();
5412 if (tc.sym.semanticRun < PASS.semanticdone)
5414 // Forward referencee of one or more bases, try again later
5415 if (tc.sym._scope)
5416 Module.addDeferredSemantic(tc.sym);
5417 return deferDsymbolSemantic(sc, idec, scx);
5421 if (idec.baseok == Baseok.done)
5423 idec.baseok = Baseok.semanticdone;
5424 objc.setMetaclass(idec, sc);
5426 // initialize vtbl
5427 if (idec.vtblOffset())
5428 idec.vtbl.push(idec); // leave room at vtbl[0] for classinfo
5430 // Cat together the vtbl[]'s from base interfaces
5431 foreach (i, b; idec.interfaces)
5433 // Skip if b has already appeared
5434 for (size_t k = 0; k < i; k++)
5436 if (b == idec.interfaces[k])
5437 goto Lcontinue;
5440 // Copy vtbl[] from base class
5441 if (b.sym.vtblOffset())
5443 size_t d = b.sym.vtbl.length;
5444 if (d > 1)
5446 idec.vtbl.pushSlice(b.sym.vtbl[1 .. d]);
5449 else
5451 idec.vtbl.append(&b.sym.vtbl);
5454 Lcontinue:
5458 idec.members.foreachDsymbol( s => s.addMember(sc, idec) );
5460 auto sc2 = idec.newScope(sc);
5462 /* Set scope so if there are forward references, we still might be able to
5463 * resolve individual members like enums.
5465 idec.members.foreachDsymbol( s => s.setScope(sc2) );
5467 idec.members.foreachDsymbol( s => s.importAll(sc2) );
5469 idec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
5471 idec.semanticRun = PASS.semanticdone;
5472 //printf("-InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type);
5474 sc2.pop();
5476 if (global.errors != errors)
5478 // The type is no good.
5479 idec.type = Type.terror;
5482 version (none)
5484 if (type.ty == Tclass && (cast(TypeClass)idec.type).sym != idec)
5486 printf("this = %p %s\n", idec, idec.toChars());
5487 printf("type = %d sym = %p\n", idec.type.ty, (cast(TypeClass)idec.type).sym);
5490 assert(idec.type.ty != Tclass || (cast(TypeClass)idec.type).sym == idec);
5492 version (none)
5494 // @@@DEPRECATED_2.120@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
5495 // Deprecated in 2.087
5496 // Made an error in 2.100, but removal depends on `scope class` being removed too
5497 // Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
5498 if (idec.storage_class & STC.scope_)
5499 error(idec.loc, "`scope` as a type constraint is obsolete. Use `scope` at the usage site.");
5505 Adds dsym as a member of scope sds.
5507 Params:
5508 dsym = dsymbol to inserted
5509 sc = scope where the dsymbol is declared
5510 sds = ScopeDsymbol where dsym is inserted
5512 extern(C++) void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
5514 auto addMemberVisitor = new AddMemberVisitor(sc, sds);
5515 dsym.accept(addMemberVisitor);
5518 private void attribAddMember(AttribDeclaration atb, Scope* sc, ScopeDsymbol sds)
5520 Dsymbols* d = atb.include(sc);
5521 if (d)
5523 Scope* sc2 = atb.newScope(sc);
5524 d.foreachDsymbol( s => s.addMember(sc2, sds) );
5525 if (sc2 != sc)
5526 sc2.pop();
5530 private extern(C++) class AddMemberVisitor : Visitor
5532 alias visit = Visitor.visit;
5534 Scope* sc;
5535 ScopeDsymbol sds;
5537 this(Scope* sc, ScopeDsymbol sds)
5539 this.sc = sc;
5540 this.sds = sds;
5543 override void visit(Dsymbol dsym)
5545 //printf("Dsymbol::addMember('%s')\n", toChars());
5546 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars());
5547 //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab);
5548 dsym.parent = sds;
5549 if (dsym.isAnonymous()) // no name, so can't add it to symbol table
5550 return;
5552 if (!sds.symtabInsert(dsym)) // if name is already defined
5554 if (dsym.isAliasDeclaration() && !dsym._scope)
5555 dsym.setScope(sc);
5556 Dsymbol s2 = sds.symtabLookup(dsym, dsym.ident);
5557 /* https://issues.dlang.org/show_bug.cgi?id=17434
5559 * If we are trying to add an import to the symbol table
5560 * that has already been introduced, then keep the one with
5561 * larger visibility. This is fine for imports because if
5562 * we have multiple imports of the same file, if a single one
5563 * is public then the symbol is reachable.
5565 if (auto i1 = dsym.isImport())
5567 if (auto i2 = s2.isImport())
5569 if (sc.explicitVisibility && sc.visibility > i2.visibility)
5570 sds.symtab.update(dsym);
5574 // If using C tag/prototype/forward declaration rules
5575 if (sc.flags & SCOPE.Cfile && !dsym.isImport())
5577 if (handleTagSymbols(*sc, dsym, s2, sds))
5578 return;
5579 if (handleSymbolRedeclarations(*sc, dsym, s2, sds))
5580 return;
5582 sds.multiplyDefined(Loc.initial, dsym, s2); // ImportC doesn't allow overloading
5583 dsym.errors = true;
5584 return;
5587 if (!s2.overloadInsert(dsym))
5589 sds.multiplyDefined(Loc.initial, dsym, s2);
5590 dsym.errors = true;
5593 if (sds.isAggregateDeclaration() || sds.isEnumDeclaration())
5595 if (dsym.ident == Id.__sizeof ||
5596 !(sc && sc.flags & SCOPE.Cfile) && (dsym.ident == Id.__xalignof || dsym.ident == Id._mangleof))
5598 .error(dsym.loc, "%s `%s` `.%s` property cannot be redefined", dsym.kind, dsym.toPrettyChars, dsym.ident.toChars());
5599 dsym.errors = true;
5605 override void visit(StaticAssert _)
5607 // we didn't add anything
5610 /*****************************
5611 * Add import to sd's symbol table.
5613 override void visit(Import imp)
5615 //printf("Import.addMember(this=%s, sds=%s, sc=%p)\n", imp.toChars(), sds.toChars(), sc);
5616 if (imp.names.length == 0)
5617 return visit(cast(Dsymbol)imp);
5618 if (imp.aliasId)
5619 visit(cast(Dsymbol)imp);
5621 /* Instead of adding the import to sds's symbol table,
5622 * add each of the alias=name pairs
5624 for (size_t i = 0; i < imp.names.length; i++)
5626 Identifier name = imp.names[i];
5627 Identifier _alias = imp.aliases[i];
5628 if (!_alias)
5629 _alias = name;
5630 auto tname = new TypeIdentifier(imp.loc, name);
5631 auto ad = new AliasDeclaration(imp.loc, _alias, tname);
5632 ad._import = imp;
5633 addMember(ad, sc, sds);
5634 imp.aliasdecls.push(ad);
5638 override void visit(AttribDeclaration atb)
5640 attribAddMember(atb, sc, sds);
5643 override void visit(StorageClassDeclaration stcd)
5645 Dsymbols* d = stcd.include(sc);
5646 if (d)
5648 Scope* sc2 = stcd.newScope(sc);
5650 d.foreachDsymbol( (s)
5652 //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars());
5653 // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol)
5654 if (auto decl = s.isDeclaration())
5656 decl.storage_class |= stcd.stc & STC.local;
5657 if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case?
5659 sdecl.stc |= stcd.stc & STC.local;
5662 s.addMember(sc2, sds);
5665 if (sc2 != sc)
5666 sc2.pop();
5670 override void visit(VisibilityDeclaration visd)
5672 if (visd.pkg_identifiers)
5674 Dsymbol tmp;
5675 Package.resolve(visd.pkg_identifiers, &tmp, null);
5676 visd.visibility.pkg = tmp ? tmp.isPackage() : null;
5677 visd.pkg_identifiers = null;
5679 if (visd.visibility.kind == Visibility.Kind.package_ && visd.visibility.pkg && sc._module)
5681 Module m = sc._module;
5683 // https://issues.dlang.org/show_bug.cgi?id=17441
5684 // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if
5685 // each package's .isModule() properites are equal.
5687 // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
5688 // This breaks package declarations of the package in question if they are declared in
5689 // the same package.d file, which _do_ have a module associated with them, and hence a non-null
5690 // isModule()
5691 if (!m.isPackage() || !visd.visibility.pkg.ident.equals(m.isPackage().ident))
5693 Package pkg = m.parent ? m.parent.isPackage() : null;
5694 if (!pkg || !visd.visibility.pkg.isAncestorPackageOf(pkg))
5695 .error(visd.loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", visd.kind(), visd.toPrettyChars(false), m.toPrettyChars(true));
5698 attribAddMember(visd, sc, sds);
5701 override void visit(StaticIfDeclaration sid)
5703 //printf("StaticIfDeclaration::addMember() '%s'\n", sid.toChars());
5704 /* This is deferred until the condition evaluated later (by the include() call),
5705 * so that expressions in the condition can refer to declarations
5706 * in the same scope, such as:
5708 * template Foo(int i)
5710 * const int j = i + 1;
5711 * static if (j == 3)
5712 * const int k;
5715 sid.scopesym = sds;
5719 override void visit(StaticForeachDeclaration sfd)
5721 // used only for caching the enclosing symbol
5722 sfd.scopesym = sds;
5725 /***************************************
5726 * Lazily initializes the scope to forward to.
5728 override void visit(ForwardingAttribDeclaration fad)
5730 fad.sym.parent = sds;
5731 sds = fad.sym;
5732 attribAddMember(fad, sc, fad.sym);
5735 override void visit(MixinDeclaration md)
5737 //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, md.memnum);
5738 md.scopesym = sds;
5741 override void visit(DebugSymbol ds)
5743 //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), ds.toChars());
5744 Module m = sds.isModule();
5745 // Do not add the member to the symbol table,
5746 // just make sure subsequent debug declarations work.
5747 if (ds.ident)
5749 if (!m)
5751 .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
5752 ds.errors = true;
5754 else
5756 if (m.debugidsNot && findCondition(*m.debugidsNot, ds.ident))
5758 .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
5759 ds.errors = true;
5761 if (!m.debugids)
5762 m.debugids = new Identifiers();
5763 m.debugids.push(ds.ident);
5766 else
5768 if (!m)
5770 .error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
5771 ds.errors = true;
5773 else
5774 m.debuglevel = ds.level;
5778 override void visit(VersionSymbol vs)
5780 //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), vs.toChars());
5781 Module m = sds.isModule();
5782 // Do not add the member to the symbol table,
5783 // just make sure subsequent debug declarations work.
5784 if (vs.ident)
5786 VersionCondition.checkReserved(vs.loc, vs.ident.toString());
5787 if (!m)
5789 .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
5790 vs.errors = true;
5792 else
5794 if (m.versionidsNot && findCondition(*m.versionidsNot, vs.ident))
5796 .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
5797 vs.errors = true;
5799 if (!m.versionids)
5800 m.versionids = new Identifiers();
5801 m.versionids.push(vs.ident);
5804 else
5806 if (!m)
5808 .error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
5809 vs.errors = true;
5811 else
5812 m.versionlevel = vs.level;
5816 override void visit(Nspace ns)
5818 visit(cast(Dsymbol)ns);
5820 if (ns.members)
5822 if (!ns.symtab)
5823 ns.symtab = new DsymbolTable();
5824 // The namespace becomes 'imported' into the enclosing scope
5825 for (Scope* sce = sc; 1; sce = sce.enclosing)
5827 ScopeDsymbol sds2 = sce.scopesym;
5828 if (sds2)
5830 sds2.importScope(ns, Visibility(Visibility.Kind.public_));
5831 break;
5834 assert(sc);
5835 sc = sc.push(ns);
5836 sc.linkage = LINK.cpp; // namespaces default to C++ linkage
5837 sc.parent = ns;
5838 ns.members.foreachDsymbol(s => s.addMember(sc, ns));
5839 sc.pop();
5843 override void visit(EnumDeclaration ed)
5845 version (none)
5847 printf("EnumDeclaration::addMember() %s\n", ed.toChars());
5848 for (size_t i = 0; i < ed.members.length; i++)
5850 EnumMember em = (*ed.members)[i].isEnumMember();
5851 printf(" member %s\n", em.toChars());
5854 if (!ed.isAnonymous())
5856 visit(cast(Dsymbol)ed);
5859 addEnumMembersToSymtab(ed, sc, sds);
5863 /*******************************************
5864 * Add members of EnumDeclaration to the symbol table(s).
5865 * Params:
5866 * ed = EnumDeclaration
5867 * sc = context of `ed`
5868 * sds = symbol table that `ed` resides in
5870 void addEnumMembersToSymtab(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
5872 const bool isCEnum = (sc.flags & SCOPE.Cfile) != 0; // it's an ImportC enum
5873 //printf("addEnumMembersToSymtab(ed: %s added: %d Cfile: %d)\n", ed.toChars(), ed.added, isCEnum);
5874 if (ed.added)
5875 return;
5876 ed.added = true;
5878 if (!ed.members)
5879 return;
5881 const bool isAnon = ed.isAnonymous();
5883 if ((isCEnum || isAnon) && !sds.symtab)
5884 sds.symtab = new DsymbolTable();
5886 if ((isCEnum || !isAnon) && !ed.symtab)
5887 ed.symtab = new DsymbolTable();
5889 ed.members.foreachDsymbol( (s)
5891 if (EnumMember em = s.isEnumMember())
5893 //printf("adding EnumMember %s to %s %d\n", em.toChars(), ed.toChars(), isCEnum);
5894 em.ed = ed;
5895 if (isCEnum)
5897 /* C doesn't add the enum member to the symbol table of the enum tag, it adds
5898 * it to the symbol table that the tag is in. This is in contrast to D, where enum
5899 * members become members of the enum tag. To accommodate this, we add
5900 * the enum members to both symbol tables.
5902 em.addMember(sc, ed); // add em to ed's symbol table
5903 em.addMember(sc, sds); // add em to symbol table that ed is in
5904 em.parent = ed; // restore it after previous addMember() changed it
5906 else
5908 em.addMember(sc, isAnon ? sds : ed);
5914 /******************************************************
5915 * Verifies if the given Identifier is a DRuntime hook. It uses the hooks
5916 * defined in `id.d`.
5918 * Params:
5919 * id = Identifier to verify
5920 * Returns:
5921 * true if `id` is a DRuntime hook
5922 * false otherwise
5924 private bool isDRuntimeHook(Identifier id)
5926 return id == Id._d_HookTraceImpl ||
5927 id == Id._d_newclassT || id == Id._d_newclassTTrace ||
5928 id == Id._d_arraycatnTX || id == Id._d_arraycatnTXTrace ||
5929 id == Id._d_newThrowable || id == Id._d_delThrowable ||
5930 id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
5931 id == Id._d_arraysetassign || id == Id._d_arraysetctor ||
5932 id == Id._d_arrayctor ||
5933 id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT ||
5934 id == Id._d_arraysetlengthTTrace ||
5935 id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace ||
5936 id == Id._d_arrayappendcTX;
5939 void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList)
5941 //printf("[%s] TemplateInstance.dsymbolSemantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst.loc.toChars(), tempinst.toChars(), tempinst, global.gag, sc);
5942 version (none)
5944 for (Dsymbol s = tempinst; s; s = s.parent)
5946 printf("\t%s\n", s.toChars());
5948 printf("Scope\n");
5949 for (Scope* scx = sc; scx; scx = scx.enclosing)
5951 printf("\t%s parent %s\n", scx._module ? scx._module.toChars() : "null", scx.parent ? scx.parent.toChars() : "null");
5955 static if (LOG)
5957 printf("\n+TemplateInstance.dsymbolSemantic('%s', this=%p)\n", tempinst.toChars(), tempinst);
5959 if (tempinst.inst) // if semantic() was already run
5961 static if (LOG)
5963 printf("-TemplateInstance.dsymbolSemantic('%s', this=%p) already run\n",
5964 tempinst.inst.toChars(), tempinst.inst);
5966 return;
5968 if (tempinst.semanticRun != PASS.initial)
5970 static if (LOG)
5972 printf("Recursive template expansion\n");
5974 auto ungag = Ungag(global.gag);
5975 if (!tempinst.gagged)
5976 global.gag = 0;
5977 .error(tempinst.loc, "%s `%s` recursive template expansion", tempinst.kind, tempinst.toPrettyChars);
5978 if (tempinst.gagged)
5979 tempinst.semanticRun = PASS.initial;
5980 else
5981 tempinst.inst = tempinst;
5982 tempinst.errors = true;
5983 return;
5986 // Get the enclosing template instance from the scope tinst
5987 tempinst.tinst = sc.tinst;
5989 // Get the instantiating module from the scope minst
5990 tempinst.minst = sc.minst;
5991 // https://issues.dlang.org/show_bug.cgi?id=10920
5992 // If the enclosing function is non-root symbol,
5993 // this instance should be speculative.
5994 if (!tempinst.tinst && sc.func && sc.func.inNonRoot())
5996 tempinst.minst = null;
5999 tempinst.gagged = (global.gag > 0);
6001 tempinst.semanticRun = PASS.semantic;
6003 static if (LOG)
6005 printf("\tdo semantic\n");
6007 /* Find template declaration first,
6008 * then run semantic on each argument (place results in tiargs[]),
6009 * last find most specialized template from overload list/set.
6011 if (!tempinst.findTempDecl(sc, null) || !tempinst.semanticTiargs(sc) || !tempinst.findBestMatch(sc, argumentList))
6013 Lerror:
6014 if (tempinst.gagged)
6016 // https://issues.dlang.org/show_bug.cgi?id=13220
6017 // Roll back status for later semantic re-running
6018 tempinst.semanticRun = PASS.initial;
6020 else
6021 tempinst.inst = tempinst;
6022 tempinst.errors = true;
6023 return;
6025 TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration();
6026 assert(tempdecl);
6028 if (global.params.v.templates)
6029 TemplateStats.incInstance(tempdecl, tempinst, global.params.v.templatesListInstances);
6031 tempdecl.checkDeprecated(tempinst.loc, sc);
6033 // If tempdecl is a mixin, disallow it
6034 if (tempdecl.ismixin)
6036 .error(tempinst.loc, "%s `%s` mixin templates are not regular templates", tempinst.kind, tempinst.toPrettyChars);
6037 goto Lerror;
6040 tempinst.hasNestedArgs(tempinst.tiargs, tempdecl.isstatic);
6041 if (tempinst.errors)
6042 goto Lerror;
6044 // Copy the tempdecl namespace (not the scope one)
6045 tempinst.cppnamespace = tempdecl.cppnamespace;
6046 if (tempinst.cppnamespace)
6047 tempinst.cppnamespace.dsymbolSemantic(sc);
6049 /* Greatly simplified semantic processing for AliasSeq templates
6051 if (tempdecl.isTrivialAliasSeq)
6053 tempinst.inst = tempinst;
6054 return aliasSeqInstanceSemantic(tempinst, sc, tempdecl);
6057 /* Greatly simplified semantic processing for Alias templates
6059 else if (tempdecl.isTrivialAlias)
6061 tempinst.inst = tempinst;
6062 return aliasInstanceSemantic(tempinst, sc, tempdecl);
6065 Expressions* fargs = argumentList.arguments; // TODO: resolve named args
6067 /* See if there is an existing TemplateInstantiation that already
6068 * implements the typeargs. If so, just refer to that one instead.
6070 tempinst.inst = tempdecl.findExistingInstance(tempinst, fargs);
6071 TemplateInstance errinst = null;
6072 if (!tempinst.inst)
6074 // So, we need to implement 'this' instance.
6076 else if (tempinst.inst.gagged && !tempinst.gagged && tempinst.inst.errors)
6078 // If the first instantiation had failed, re-run semantic,
6079 // so that error messages are shown.
6080 errinst = tempinst.inst;
6082 else
6084 // It's a match
6085 tempinst.parent = tempinst.inst.parent;
6086 tempinst.errors = tempinst.inst.errors;
6088 // If both this and the previous instantiation were gagged,
6089 // use the number of errors that happened last time.
6090 global.errors += tempinst.errors;
6091 global.gaggedErrors += tempinst.errors;
6093 // If the first instantiation was gagged, but this is not:
6094 if (tempinst.inst.gagged)
6096 // It had succeeded, mark it is a non-gagged instantiation,
6097 // and reuse it.
6098 tempinst.inst.gagged = tempinst.gagged;
6101 tempinst.tnext = tempinst.inst.tnext;
6102 tempinst.inst.tnext = tempinst;
6104 /* A module can have explicit template instance and its alias
6105 * in module scope (e,g, `alias Base64 = Base64Impl!('+', '/');`).
6106 * If the first instantiation 'inst' had happened in non-root module,
6107 * compiler can assume that its instantiated code would be included
6108 * in the separately compiled obj/lib file (e.g. phobos.lib).
6110 * However, if 'this' second instantiation happened in root module,
6111 * compiler might need to invoke its codegen
6112 * (https://issues.dlang.org/show_bug.cgi?id=2500 & https://issues.dlang.org/show_bug.cgi?id=2644).
6113 * But whole import graph is not determined until all semantic pass finished,
6114 * so 'inst' should conservatively finish the semantic3 pass for the codegen.
6116 if (tempinst.minst && tempinst.minst.isRoot() && !(tempinst.inst.minst && tempinst.inst.minst.isRoot()))
6118 /* Swap the position of 'inst' and 'this' in the instantiation graph.
6119 * Then, the primary instance `inst` will be changed to a root instance,
6120 * along with all members of `inst` having their scopes updated.
6122 * Before:
6123 * non-root -> A!() -> B!()[inst] -> C!() { members[non-root] }
6125 * root -> D!() -> B!()[this]
6127 * After:
6128 * non-root -> A!() -> B!()[this]
6130 * root -> D!() -> B!()[inst] -> C!() { members[root] }
6132 Module mi = tempinst.minst;
6133 TemplateInstance ti = tempinst.tinst;
6134 tempinst.minst = tempinst.inst.minst;
6135 tempinst.tinst = tempinst.inst.tinst;
6136 tempinst.inst.minst = mi;
6137 tempinst.inst.tinst = ti;
6139 /* https://issues.dlang.org/show_bug.cgi?id=21299
6140 `minst` has been updated on the primary instance `inst` so it is
6141 now coming from a root module, however all Dsymbol `inst.members`
6142 of the instance still have their `_scope.minst` pointing at the
6143 original non-root module. We must now propagate `minst` to all
6144 members so that forward referenced dependencies that get
6145 instantiated will also be appended to the root module, otherwise
6146 there will be undefined references at link-time. */
6147 extern (C++) final class InstMemberWalker : Visitor
6149 alias visit = Visitor.visit;
6150 TemplateInstance inst;
6152 extern (D) this(TemplateInstance inst) scope @safe
6154 this.inst = inst;
6157 override void visit(Dsymbol d)
6159 if (d._scope)
6160 d._scope.minst = inst.minst;
6163 override void visit(ScopeDsymbol sds)
6165 sds.members.foreachDsymbol( s => s.accept(this) );
6166 visit(cast(Dsymbol)sds);
6169 override void visit(AttribDeclaration ad)
6171 ad.include(null).foreachDsymbol( s => s.accept(this) );
6172 visit(cast(Dsymbol)ad);
6175 override void visit(ConditionalDeclaration cd)
6177 if (cd.condition.inc)
6178 visit(cast(AttribDeclaration)cd);
6179 else
6180 visit(cast(Dsymbol)cd);
6183 scope v = new InstMemberWalker(tempinst.inst);
6184 tempinst.inst.accept(v);
6186 if (!global.params.allInst &&
6187 tempinst.minst) // if inst was not speculative...
6189 assert(!tempinst.minst.isRoot()); // ... it was previously appended to a non-root module
6190 // Append again to the root module members[], so that the instance will
6191 // get codegen chances (depending on `tempinst.inst.needsCodegen()`).
6192 tempinst.inst.appendToModuleMember();
6195 assert(tempinst.inst.memberOf && tempinst.inst.memberOf.isRoot(), "no codegen chances");
6198 // modules imported by an existing instance should be added to the module
6199 // that instantiates the instance.
6200 if (tempinst.minst)
6201 foreach(imp; tempinst.inst.importedModules)
6202 if (!tempinst.minst.aimports.contains(imp))
6203 tempinst.minst.aimports.push(imp);
6205 static if (LOG)
6207 printf("\tit's a match with instance %p, %d\n", tempinst.inst, tempinst.inst.semanticRun);
6209 return;
6211 static if (LOG)
6213 printf("\timplement template instance %s '%s'\n", tempdecl.parent.toChars(), tempinst.toChars());
6214 printf("\ttempdecl %s\n", tempdecl.toChars());
6216 uint errorsave = global.errors;
6218 tempinst.inst = tempinst;
6219 tempinst.parent = tempinst.enclosing ? tempinst.enclosing : tempdecl.parent;
6220 //printf("parent = '%s'\n", parent.kind());
6222 if (global.params.v.templates)
6223 TemplateStats.incUnique(tempdecl, tempinst);
6225 TemplateInstance tempdecl_instance_idx = tempdecl.addInstance(tempinst);
6227 //getIdent();
6229 // Store the place we added it to in target_symbol_list(_idx) so we can
6230 // remove it later if we encounter an error.
6231 Dsymbols* target_symbol_list = tempinst.appendToModuleMember();
6232 size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list.length - 1 : 0;
6234 // Copy the syntax trees from the TemplateDeclaration
6235 tempinst.members = Dsymbol.arraySyntaxCopy(tempdecl.members);
6237 // resolve TemplateThisParameter
6238 for (size_t i = 0; i < tempdecl.parameters.length; i++)
6240 if ((*tempdecl.parameters)[i].isTemplateThisParameter() is null)
6241 continue;
6242 Type t = isType((*tempinst.tiargs)[i]);
6243 assert(t);
6244 if (StorageClass stc = ModToStc(t.mod))
6246 //printf("t = %s, stc = x%llx\n", t.toChars(), stc);
6247 auto s = new Dsymbols();
6248 s.push(new StorageClassDeclaration(stc, tempinst.members));
6249 tempinst.members = s;
6251 break;
6254 // Create our own scope for the template parameters
6255 Scope* _scope = tempdecl._scope;
6256 if (tempdecl.semanticRun == PASS.initial)
6258 .error(tempinst.loc, "%s `%s` template instantiation `%s` forward references template declaration `%s`",
6259 tempinst.kind, tempinst.toPrettyChars, tempinst.toChars(), tempdecl.toChars());
6260 return;
6263 static if (LOG)
6265 printf("\tcreate scope for template parameters '%s'\n", tempinst.toChars());
6267 tempinst.argsym = new ScopeDsymbol();
6268 tempinst.argsym.parent = _scope.parent;
6269 _scope = _scope.push(tempinst.argsym);
6270 _scope.tinst = tempinst;
6271 _scope.minst = tempinst.minst;
6272 //scope.stc = 0;
6274 // Declare each template parameter as an alias for the argument type
6275 Scope* paramscope = _scope.push();
6276 paramscope.stc = 0;
6277 paramscope.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=14169
6278 // template parameters should be public
6279 tempinst.declareParameters(paramscope);
6280 paramscope.pop();
6282 // Add members of template instance to template instance symbol table
6283 //parent = scope.scopesym;
6284 tempinst.symtab = new DsymbolTable();
6286 tempinst.members.foreachDsymbol( (s)
6288 static if (LOG)
6290 printf("\t adding member '%s' %p kind %s to '%s'\n", s.toChars(), s, s.kind(), tempinst.toChars());
6292 s.addMember(_scope, tempinst);
6295 static if (LOG)
6297 printf("adding members done\n");
6300 /* See if there is only one member of template instance, and that
6301 * member has the same name as the template instance.
6302 * If so, this template instance becomes an alias for that member.
6304 //printf("members.length = %d\n", tempinst.members.length);
6305 if (tempinst.members.length)
6307 Dsymbol s;
6308 if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s)
6310 //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
6311 //printf("setting aliasdecl\n");
6312 tempinst.aliasdecl = s;
6316 /* If function template declaration
6318 if (fargs && tempinst.aliasdecl)
6320 if (auto fd = tempinst.aliasdecl.isFuncDeclaration())
6322 /* Transmit fargs to type so that TypeFunction.dsymbolSemantic() can
6323 * resolve any "auto ref" storage classes.
6325 if (fd.type)
6326 if (auto tf = fd.type.isTypeFunction())
6327 tf.fargs = fargs;
6331 // Do semantic() analysis on template instance members
6332 static if (LOG)
6334 printf("\tdo semantic() on template instance members '%s'\n", tempinst.toChars());
6336 Scope* sc2;
6337 sc2 = _scope.push(tempinst);
6338 //printf("enclosing = %d, sc.parent = %s\n", tempinst.enclosing, sc.parent.toChars());
6339 sc2.parent = tempinst;
6340 sc2.tinst = tempinst;
6341 sc2.minst = tempinst.minst;
6342 sc2.stc &= ~STC.deprecated_;
6343 tempinst.tryExpandMembers(sc2);
6345 tempinst.semanticRun = PASS.semanticdone;
6347 /* ConditionalDeclaration may introduce eponymous declaration,
6348 * so we should find it once again after semantic.
6350 if (tempinst.members.length)
6352 Dsymbol s;
6353 if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s)
6355 if (!tempinst.aliasdecl || tempinst.aliasdecl != s)
6357 //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
6358 //printf("setting aliasdecl 2\n");
6359 tempinst.aliasdecl = s;
6364 if (global.errors != errorsave)
6365 goto Laftersemantic;
6367 /* If any of the instantiation members didn't get semantic() run
6368 * on them due to forward references, we cannot run semantic2()
6369 * or semantic3() yet.
6372 bool found_deferred_ad = false;
6373 for (size_t i = 0; i < Module.deferred.length; i++)
6375 Dsymbol sd = Module.deferred[i];
6376 AggregateDeclaration ad = sd.isAggregateDeclaration();
6377 if (ad && ad.parent && ad.parent.isTemplateInstance())
6379 //printf("deferred template aggregate: %s %s\n",
6380 // sd.parent.toChars(), sd.toChars());
6381 found_deferred_ad = true;
6382 if (ad.parent == tempinst)
6384 ad.deferred = tempinst;
6385 break;
6389 if (found_deferred_ad || Module.deferred.length)
6390 goto Laftersemantic;
6393 /* The problem is when to parse the initializer for a variable.
6394 * Perhaps VarDeclaration.dsymbolSemantic() should do it like it does
6395 * for initializers inside a function.
6397 //if (sc.parent.isFuncDeclaration())
6399 /* https://issues.dlang.org/show_bug.cgi?id=782
6400 * this has problems if the classes this depends on
6401 * are forward referenced. Find a way to defer semantic()
6402 * on this template.
6404 tempinst.semantic2(sc2);
6406 if (global.errors != errorsave)
6407 goto Laftersemantic;
6409 if ((sc.func || (sc.flags & SCOPE.fullinst)) && !tempinst.tinst)
6411 /* If a template is instantiated inside function, the whole instantiation
6412 * should be done at that position. But, immediate running semantic3 of
6413 * dependent templates may cause unresolved forward reference.
6414 * https://issues.dlang.org/show_bug.cgi?id=9050
6415 * To avoid the issue, don't run semantic3 until semantic and semantic2 done.
6417 TemplateInstances deferred;
6418 tempinst.deferred = &deferred;
6420 //printf("Run semantic3 on %s\n", toChars());
6422 /* https://issues.dlang.org/show_bug.cgi?id=23965
6423 * DRuntime hooks are not deprecated, but may be used for deprecated
6424 * types. Deprecations are disabled while analysing hooks to avoid
6425 * spurious error messages.
6427 auto saveUseDeprecated = global.params.useDeprecated;
6428 if (sc.isDeprecated() && isDRuntimeHook(tempinst.name))
6429 global.params.useDeprecated = DiagnosticReporting.off;
6431 tempinst.trySemantic3(sc2);
6433 global.params.useDeprecated = saveUseDeprecated;
6435 for (size_t i = 0; i < deferred.length; i++)
6437 //printf("+ run deferred semantic3 on %s\n", deferred[i].toChars());
6438 deferred[i].semantic3(null);
6441 tempinst.deferred = null;
6443 else if (tempinst.tinst)
6445 bool doSemantic3 = false;
6446 FuncDeclaration fd;
6447 if (tempinst.aliasdecl)
6448 fd = tempinst.aliasdecl.toAlias2().isFuncDeclaration();
6450 if (fd)
6452 /* Template function instantiation should run semantic3 immediately
6453 * for attribute inference.
6455 scope fld = fd.isFuncLiteralDeclaration();
6456 if (fld && fld.tok == TOK.reserved)
6457 doSemantic3 = true;
6458 else if (sc.func)
6459 doSemantic3 = true;
6461 else if (sc.func)
6463 /* A lambda function in template arguments might capture the
6464 * instantiated scope context. For the correct context inference,
6465 * all instantiated functions should run the semantic3 immediately.
6466 * See also compilable/test14973.d
6468 foreach (oarg; tempinst.tdtypes)
6470 auto s = getDsymbol(oarg);
6471 if (!s)
6472 continue;
6474 if (auto td = s.isTemplateDeclaration())
6476 if (!td.literal)
6477 continue;
6478 assert(td.members && td.members.length == 1);
6479 s = (*td.members)[0];
6481 if (auto fld = s.isFuncLiteralDeclaration())
6483 if (fld.tok == TOK.reserved)
6485 doSemantic3 = true;
6486 break;
6490 //printf("[%s] %s doSemantic3 = %d\n", tempinst.tinst.loc.toChars(), tempinst.tinst.toChars(), doSemantic3);
6492 if (doSemantic3)
6493 tempinst.trySemantic3(sc2);
6495 TemplateInstance ti = tempinst.tinst;
6496 int nest = 0;
6497 while (ti && !ti.deferred && ti.tinst)
6499 ti = ti.tinst;
6500 if (++nest > global.recursionLimit)
6502 global.gag = 0; // ensure error message gets printed
6503 .error(tempinst.loc, "%s `%s` recursive expansion", tempinst.kind, tempinst.toPrettyChars);
6504 fatal();
6507 if (ti && ti.deferred)
6509 //printf("deferred semantic3 of %p %s, ti = %s, ti.deferred = %p\n", this, toChars(), ti.toChars());
6510 for (size_t i = 0;; i++)
6512 if (i == ti.deferred.length)
6514 ti.deferred.push(tempinst);
6515 break;
6517 if ((*ti.deferred)[i] == tempinst)
6518 break;
6523 if (tempinst.aliasdecl)
6525 /* https://issues.dlang.org/show_bug.cgi?id=13816
6526 * AliasDeclaration tries to resolve forward reference
6527 * twice (See inuse check in AliasDeclaration.toAlias()). It's
6528 * necessary to resolve mutual references of instantiated symbols, but
6529 * it will left a true recursive alias in tuple declaration - an
6530 * AliasDeclaration A refers TupleDeclaration B, and B contains A
6531 * in its elements. To correctly make it an error, we strictly need to
6532 * resolve the alias of eponymous member.
6534 tempinst.aliasdecl = tempinst.aliasdecl.toAlias2();
6536 // stop AliasAssign tuple building
6537 if (auto td = tempinst.aliasdecl.isTupleDeclaration())
6538 td.building = false;
6541 Laftersemantic:
6542 sc2.pop();
6543 _scope.pop();
6545 // Give additional context info if error occurred during instantiation
6546 if (global.errors != errorsave)
6548 if (!tempinst.errors)
6550 if (!tempdecl.literal)
6551 .error(tempinst.loc, "%s `%s` error instantiating", tempinst.kind, tempinst.toPrettyChars);
6552 if (tempinst.tinst)
6553 tempinst.tinst.printInstantiationTrace();
6555 tempinst.errors = true;
6556 if (tempinst.gagged)
6558 // Errors are gagged, so remove the template instance from the
6559 // instance/symbol lists we added it to and reset our state to
6560 // finish clean and so we can try to instantiate it again later
6561 // (see https://issues.dlang.org/show_bug.cgi?id=4302 and https://issues.dlang.org/show_bug.cgi?id=6602).
6562 tempdecl.removeInstance(tempdecl_instance_idx);
6563 if (target_symbol_list)
6565 // Because we added 'this' in the last position above, we
6566 // should be able to remove it without messing other indices up.
6567 assert((*target_symbol_list)[target_symbol_list_idx] == tempinst);
6568 target_symbol_list.remove(target_symbol_list_idx);
6569 tempinst.memberOf = null; // no longer a member
6571 tempinst.semanticRun = PASS.initial;
6572 tempinst.inst = null;
6573 tempinst.symtab = null;
6576 else if (errinst)
6578 /* https://issues.dlang.org/show_bug.cgi?id=14541
6579 * If the previous gagged instance had failed by
6580 * circular references, currrent "error reproduction instantiation"
6581 * might succeed, because of the difference of instantiated context.
6582 * On such case, the cached error instance needs to be overridden by the
6583 * succeeded instance.
6585 //printf("replaceInstance()\n");
6586 assert(errinst.errors);
6587 auto ti1 = TemplateInstanceBox(errinst);
6588 tempdecl.instances.remove(ti1);
6590 auto ti2 = TemplateInstanceBox(tempinst);
6591 tempdecl.instances[ti2] = tempinst;
6594 static if (LOG)
6596 printf("-TemplateInstance.dsymbolSemantic('%s', this=%p)\n", tempinst.toChars(), tempinst);
6600 /******************************************************
6601 * Do template instance semantic for isAliasSeq templates.
6602 * This is a greatly simplified version of templateInstanceSemantic().
6604 private
6605 void aliasSeqInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclaration tempdecl)
6607 //printf("[%s] aliasSeqInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
6608 Scope* paramscope = sc.push();
6609 paramscope.stc = 0;
6610 paramscope.visibility = Visibility(Visibility.Kind.public_);
6612 TemplateTupleParameter ttp = (*tempdecl.parameters)[0].isTemplateTupleParameter();
6613 Tuple va = tempinst.tdtypes[0].isTuple();
6614 Declaration d = new TupleDeclaration(tempinst.loc, ttp.ident, &va.objects);
6615 d.storage_class |= STC.templateparameter;
6616 d.dsymbolSemantic(sc);
6618 paramscope.pop();
6620 tempinst.aliasdecl = d;
6622 tempinst.semanticRun = PASS.semanticdone;
6625 /******************************************************
6626 * Do template instance semantic for isAlias templates.
6627 * This is a greatly simplified version of templateInstanceSemantic().
6629 private
6630 void aliasInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclaration tempdecl)
6632 //printf("[%s] aliasInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
6633 Scope* paramscope = sc.push();
6634 paramscope.stc = 0;
6635 paramscope.visibility = Visibility(Visibility.Kind.public_);
6637 TemplateTypeParameter ttp = (*tempdecl.parameters)[0].isTemplateTypeParameter();
6638 Type ta = tempinst.tdtypes[0].isType();
6639 auto ad = tempdecl.onemember.isAliasDeclaration();
6641 // Note: qualifiers can be in both 'ad.type.mod' and 'ad.storage_class'
6642 Declaration d = new AliasDeclaration(tempinst.loc, ttp.ident, ta.addMod(ad.type.mod));
6643 d.storage_class |= STC.templateparameter | ad.storage_class;
6644 d.dsymbolSemantic(sc);
6646 paramscope.pop();
6648 tempinst.aliasdecl = d;
6650 tempinst.semanticRun = PASS.semanticdone;
6653 // function used to perform semantic on AliasDeclaration
6654 void aliasSemantic(AliasDeclaration ds, Scope* sc)
6656 //printf("AliasDeclaration::semantic() %s\n", ds.toChars());
6658 // as DsymbolSemanticVisitor::visit(AliasDeclaration), in case we're called first.
6659 // see https://issues.dlang.org/show_bug.cgi?id=21001
6660 ds.storage_class |= sc.stc & STC.deprecated_;
6661 ds.visibility = sc.visibility;
6662 ds.userAttribDecl = sc.userAttribDecl;
6664 void normalRet()
6666 ds.inuse = 0;
6667 ds.semanticRun = PASS.semanticdone;
6669 if (auto sx = ds.overnext)
6671 ds.overnext = null;
6672 if (!ds.overloadInsert(sx))
6673 ScopeDsymbol.multiplyDefined(Loc.initial, sx, ds);
6677 void errorRet()
6679 ds.aliassym = null;
6680 ds.type = Type.terror;
6681 ds.inuse = 0;
6682 normalRet();
6685 // preserve the original type
6686 if (!ds.originalType && ds.type)
6687 ds.originalType = ds.type.syntaxCopy();
6689 if (ds.aliassym)
6691 auto fd = ds.aliassym.isFuncLiteralDeclaration();
6692 auto td = ds.aliassym.isTemplateDeclaration();
6693 if (fd || td && td.literal)
6695 if (fd && fd.semanticRun >= PASS.semanticdone)
6696 return normalRet();
6698 Expression e = new FuncExp(ds.loc, ds.aliassym);
6699 e = e.expressionSemantic(sc);
6700 if (auto fe = e.isFuncExp())
6702 ds.aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd;
6703 return normalRet();
6705 else
6706 return errorRet();
6709 if (ds.aliassym.isTemplateInstance())
6710 ds.aliassym.dsymbolSemantic(sc);
6711 return normalRet();
6713 ds.inuse = 1;
6715 // Given:
6716 // alias foo.bar.abc def;
6717 // it is not knowable from the syntax whether `def` is an alias
6718 // for type `foo.bar.abc` or an alias for symbol `foo.bar.abc`. It is up to the semantic()
6719 // pass to distinguish.
6720 // If it is a type, then `.type` is set and getType() will return that
6721 // type. If it is a symbol, then `.aliassym` is set and type is `null` -
6722 // toAlias() will return `.aliassym`
6724 const errors = global.errors;
6725 Type oldtype = ds.type;
6727 // Ungag errors when not instantiated DeclDefs scope alias
6728 auto ungag = Ungag(global.gag);
6729 //printf("%s parent = %s, gag = %d, instantiated = %d\n", ds.toChars(), ds.parent.toChars(), global.gag, ds.isInstantiated() !is null);
6730 if (ds.parent && global.gag && !ds.isInstantiated() && !ds.toParent2().isFuncDeclaration() && (sc.minst || sc.tinst))
6732 //printf("%s type = %s\n", ds.toPrettyChars(), ds.type.toChars());
6733 global.gag = 0;
6736 // https://issues.dlang.org/show_bug.cgi?id=18480
6737 // Detect `alias sym = sym;` to prevent creating loops in overload overnext lists.
6738 if (auto tident = ds.type.isTypeIdentifier())
6740 // Selective imports are allowed to alias to the same name `import mod : sym=sym`.
6741 if (!ds._import)
6743 if (tident.ident is ds.ident && !tident.idents.length)
6745 error(ds.loc, "`alias %s = %s;` cannot alias itself, use a qualified name to create an overload set",
6746 ds.ident.toChars(), tident.ident.toChars());
6747 ds.type = Type.terror;
6751 /* This section is needed because Type.resolve() will:
6752 * const x = 3;
6753 * alias y = x;
6754 * try to convert identifier x to 3.
6756 auto s = ds.type.toDsymbol(sc);
6757 if (errors != global.errors)
6758 return errorRet();
6759 if (s == ds)
6761 .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
6762 return errorRet();
6764 if (!s || !s.isEnumMember())
6766 Type t;
6767 Expression e;
6768 Scope* sc2 = sc;
6769 if (ds.storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.disable))
6771 // For 'ref' to be attached to function types, and picked
6772 // up by Type.resolve(), it has to go into sc.
6773 sc2 = sc.push();
6774 sc2.stc |= ds.storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
6776 ds.type = ds.type.addSTC(ds.storage_class);
6777 ds.type.resolve(ds.loc, sc2, e, t, s);
6778 if (sc2 != sc)
6779 sc2.pop();
6781 if (e) // Try to convert Expression to Dsymbol
6783 // TupleExp is naturally converted to a TupleDeclaration
6784 if (auto te = e.isTupleExp())
6785 s = new TupleDeclaration(te.loc, ds.ident, cast(Objects*)te.exps);
6786 else
6788 s = getDsymbol(e);
6789 if (!s)
6791 if (e.op != EXP.error)
6792 .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
6793 return errorRet();
6797 ds.type = t;
6799 if (s == ds)
6801 assert(global.errors);
6802 return errorRet();
6804 if (s) // it's a symbolic alias
6806 //printf("alias %s resolved to %s %s\n", ds.toChars(), s.kind(), s.toChars());
6807 ds.type = null;
6808 ds.aliassym = s;
6810 else // it's a type alias
6812 //printf("alias %s resolved to type %s\n", ds.toChars(), ds.type.toChars());
6813 ds.type = ds.type.typeSemantic(ds.loc, sc);
6814 ds.aliassym = null;
6817 if (global.gag && errors != global.errors)
6818 return errorRet();
6820 normalRet();
6823 /********************
6824 * Perform semantic on AliasAssignment.
6825 * Has a lot of similarities to aliasSemantic(). Perhaps they should share code.
6827 private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
6829 //printf("AliasAssign::semantic() %p, %s\n", ds, ds.ident.toChars());
6831 void errorRet()
6833 ds.errors = true;
6834 ds.type = Type.terror;
6835 ds.semanticRun = PASS.semanticdone;
6836 return;
6839 /* Find the AliasDeclaration corresponding to ds.
6840 * Returns: AliasDeclaration if found, null if error
6842 AliasDeclaration findAliasDeclaration(AliasAssign ds, Scope* sc)
6844 Dsymbol scopesym;
6845 Dsymbol as = sc.search(ds.loc, ds.ident, scopesym);
6846 if (!as)
6848 .error(ds.loc, "%s `%s` undefined identifier `%s`", ds.kind, ds.toPrettyChars, ds.ident.toChars());
6849 return null;
6851 if (as.errors)
6852 return null;
6854 auto ad = as.isAliasDeclaration();
6855 if (!ad)
6857 .error(ds.loc, "%s `%s` identifier `%s` must be an alias declaration", ds.kind, ds.toPrettyChars, as.toChars());
6858 return null;
6861 if (ad.overnext)
6863 error(ds.loc, "%s `%s` cannot reassign overloaded alias", ds.kind, ds.toPrettyChars);
6864 return null;
6867 // Check constraints on the parent
6868 auto adParent = ad.toParent();
6869 if (adParent != ds.toParent())
6871 if (!adParent)
6872 adParent = ds.toParent();
6873 .error(ds.loc, "`%s` must have same parent `%s` as alias `%s`", ds.ident.toChars(), adParent.toChars(), ad.toChars());
6874 return null;
6876 if (!adParent.isTemplateInstance())
6878 .error(ds.loc, "%s `%s` must be a member of a template", ds.kind, ds.toPrettyChars);
6879 return null;
6882 return ad;
6885 auto aliassym = findAliasDeclaration(ds, sc);
6886 if (!aliassym)
6887 return errorRet();
6889 if (aliassym.adFlags & Declaration.wasRead)
6891 if (!aliassym.errors)
6892 error(ds.loc, "%s was read, so cannot reassign", aliassym.toChars());
6893 aliassym.errors = true;
6894 return errorRet();
6897 aliassym.adFlags |= Declaration.ignoreRead; // temporarilly allow reads of aliassym
6899 const storage_class = sc.stc & (STC.deprecated_ | STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
6901 if (ds.aliassym)
6903 auto fd = ds.aliassym.isFuncLiteralDeclaration();
6904 auto td = ds.aliassym.isTemplateDeclaration();
6905 if (fd && fd.semanticRun >= PASS.semanticdone)
6908 else if (fd || td && td.literal)
6911 Expression e = new FuncExp(ds.loc, ds.aliassym);
6912 e = e.expressionSemantic(sc);
6913 auto fe = e.isFuncExp();
6914 if (!fe)
6915 return errorRet();
6916 ds.aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd;
6918 else if (ds.aliassym.isTemplateInstance())
6919 ds.aliassym.dsymbolSemantic(sc);
6921 aliassym.type = null;
6922 aliassym.aliassym = ds.aliassym;
6923 return;
6926 /* Given:
6927 * abc = def;
6928 * it is not knownable from the syntax whether `def` is a type or a symbol.
6929 * It appears here as `ds.type`. Do semantic analysis on `def` to disambiguate.
6932 const errors = global.errors;
6933 Dsymbol s;
6935 // Try AliasSeq optimization
6936 if (auto ti = ds.type.isTypeInstance())
6938 if (!ti.tempinst.findTempDecl(sc, null))
6939 return errorRet();
6940 if (auto tempinst = isAliasSeq(sc, ti))
6942 s = aliasAssignInPlace(sc, tempinst, aliassym);
6943 if (!s)
6944 return errorRet();
6945 goto Lsymdone;
6949 /* This section is needed because Type.resolve() will:
6950 * const x = 3;
6951 * alias y = x;
6952 * try to convert identifier x to 3.
6954 s = ds.type.toDsymbol(sc);
6955 if (errors != global.errors)
6956 return errorRet();
6957 if (s == aliassym)
6959 .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
6960 return errorRet();
6963 if (!s || !s.isEnumMember())
6965 Type t;
6966 Expression e;
6967 Scope* sc2 = sc;
6968 if (storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable))
6970 // For 'ref' to be attached to function types, and picked
6971 // up by Type.resolve(), it has to go into sc.
6972 sc2 = sc.push();
6973 sc2.stc |= storage_class & (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable);
6975 ds.type = ds.type.addSTC(storage_class);
6976 ds.type.resolve(ds.loc, sc2, e, t, s);
6977 if (sc2 != sc)
6978 sc2.pop();
6980 if (e) // Try to convert Expression to Dsymbol
6982 // TupleExp is naturally converted to a TupleDeclaration
6983 if (auto te = e.isTupleExp())
6984 s = new TupleDeclaration(te.loc, ds.ident, cast(Objects*)te.exps);
6985 else
6987 s = getDsymbol(e);
6988 if (!s)
6990 if (e.op != EXP.error)
6991 .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
6992 return errorRet();
6996 ds.type = t;
6998 if (s == aliassym)
7000 assert(global.errors);
7001 return errorRet();
7004 if (s) // it's a symbolic alias
7006 Lsymdone:
7007 //printf("alias %s resolved to %s %s\n", toChars(), s.kind(), s.toChars());
7008 aliassym.type = null;
7009 aliassym.aliassym = s;
7010 aliassym.storage_class |= sc.stc & STC.deprecated_;
7011 aliassym.visibility = sc.visibility;
7012 aliassym.userAttribDecl = sc.userAttribDecl;
7014 else // it's a type alias
7016 //printf("alias %s resolved to type %s\n", toChars(), type.toChars());
7017 aliassym.type = ds.type.typeSemantic(ds.loc, sc);
7018 aliassym.aliassym = null;
7022 aliassym.adFlags &= ~Declaration.ignoreRead;
7024 if (aliassym.type && aliassym.type.ty == Terror ||
7025 global.gag && errors != global.errors)
7027 aliassym.type = Type.terror;
7028 aliassym.aliassym = null;
7029 return errorRet();
7032 ds.semanticRun = PASS.semanticdone;
7035 /***************************************
7036 * Expands template instance arguments inside 'alias assign' target declaration (aliassym),
7037 * instead of inside 'tempinst.tiargs' every time.
7038 * Params:
7039 * tempinst = AliasSeq instance
7040 * aliassym = the AliasDeclaration corresponding to AliasAssign
7041 * Returns:
7042 * null.
7044 private TupleDeclaration aliasAssignInPlace(Scope* sc, TemplateInstance tempinst,
7045 AliasDeclaration aliassym)
7047 // Mark instance with semantic done, not needed but just in case.
7048 tempinst.inst = tempinst;
7049 tempinst.semanticRun = PASS.semanticdone;
7050 TupleDeclaration td;
7051 if (aliassym.type)
7053 // Convert TypeTuple to TupleDeclaration to avoid back and forth allocations
7054 // in the assignment process
7055 if (auto tt = aliassym.type.isTypeTuple())
7057 auto objs = new Objects(tt.arguments.length);
7058 foreach (i, p; *tt.arguments)
7059 (*objs)[i] = p.type;
7060 td = new TupleDeclaration(tempinst.loc, aliassym.ident, objs);
7061 td.storage_class |= STC.templateparameter;
7062 td.building = true;
7063 aliassym.type = null;
7065 else if (aliassym.type.isTypeError())
7066 return null;
7069 else if (auto otd = aliassym.aliassym.isTupleDeclaration())
7071 if (otd.building)
7072 td = otd;
7073 else
7075 td = new TupleDeclaration(tempinst.loc, aliassym.ident, otd.objects.copy());
7076 td.storage_class |= STC.templateparameter;
7077 td.building = true;
7080 // If starting from single element in aliassym (td == null) we need to build the tuple
7081 // after semanticTiargs to keep same semantics (for example a FuncLiteraldeclaration
7082 // template argument is converted to FuncExp)
7083 if (td)
7084 aliassym.aliassym = td;
7085 aliassym.semanticRun = PASS.semanticdone;
7086 if (!TemplateInstance.semanticTiargs(tempinst.loc, sc, tempinst.tiargs, 0, td))
7088 tempinst.errors = true;
7089 return null;
7091 // The alias will stop tuple 'building' mode when used (in AliasDeclaration.toAlias(),
7092 // then TupleDeclaration.getType() will work again)
7093 aliassym.semanticRun = PASS.initial;
7094 if (!td)
7096 td = new TupleDeclaration(tempinst.loc, aliassym.ident, tempinst.tiargs);
7097 td.storage_class |= STC.templateparameter;
7098 td.building = true;
7099 return td;
7102 auto tiargs = tempinst.tiargs;
7103 size_t oldlen = td.objects.length;
7104 size_t origstart;
7105 size_t insertidx;
7106 size_t insertlen;
7107 foreach (i, o; *tiargs)
7109 if (o !is td)
7111 ++insertlen;
7112 continue;
7114 // tuple contains itself (tuple = AliasSeq!(..., tuple, ...))
7115 if (insertlen) // insert any left element before
7117 td.objects.insert(insertidx, (*tiargs)[i - insertlen .. i]);
7118 if (insertidx == 0) // reset original tuple start point
7119 origstart = insertlen;
7120 insertlen = 0;
7122 if (insertidx) // insert tuple if found more than one time
7124 td.objects.reserve(oldlen); // reserve first to assert a valid slice
7125 td.objects.pushSlice((*td.objects)[origstart .. origstart + oldlen]);
7127 insertidx = td.objects.length;
7129 if (insertlen)
7131 if (insertlen != tiargs.length) // insert any left element
7132 td.objects.pushSlice((*tiargs)[$ - insertlen .. $]);
7133 else
7134 // just assign tiargs if tuple = AliasSeq!(nottuple, nottuple...)
7135 td.objects = tempinst.tiargs;
7137 return td;
7140 /***************************************
7141 * Check if a template instance is a trivial AliasSeq but without other overloads.
7142 * We can only be 100% sure of being AliasSeq after running semanticTiargs()
7143 * and findBestMatch() but this optimization must happen before that.
7145 private TemplateInstance isAliasSeq(Scope* sc, TypeInstance ti)
7147 auto tovers = ti.tempinst.tempdecl.isOverloadSet();
7148 foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
7150 Dsymbol dstart = tovers ? tovers.a[oi] : ti.tempinst.tempdecl;
7151 int r = overloadApply(dstart, (Dsymbol s)
7153 auto td = s.isTemplateDeclaration();
7154 if (!td || !td.isTrivialAliasSeq)
7155 return 1;
7156 return 0;
7158 if (r)
7159 return null;
7161 return ti.tempinst;
7164 /***************************************
7165 * Find all instance fields in `ad`, then push them into `fields`.
7167 * Runs semantic() for all instance field variables, but also
7168 * the field types can remain yet not resolved forward references,
7169 * except direct recursive definitions.
7170 * After the process sizeok is set to Sizeok.fwd.
7172 * Params:
7173 * ad = the AggregateDeclaration to examine
7174 * Returns:
7175 * false if any errors occur.
7177 bool determineFields(AggregateDeclaration ad)
7179 if (ad._scope)
7180 dsymbolSemantic(ad, null);
7181 if (ad.sizeok != Sizeok.none)
7182 return true;
7184 //printf("determineFields() %s, fields.length = %d\n", toChars(), fields.length);
7185 // determineFields can be called recursively from one of the fields's v.semantic
7186 ad.fields.setDim(0);
7188 static int func(Dsymbol s, void* ctx)
7190 auto ad = cast(AggregateDeclaration)ctx;
7191 auto v = s.isVarDeclaration();
7192 if (!v)
7193 return 0;
7194 if (v.storage_class & STC.manifest)
7195 return 0;
7197 if (v.semanticRun < PASS.semanticdone)
7198 v.dsymbolSemantic(null);
7199 // Return in case a recursive determineFields triggered by v.semantic already finished
7200 if (ad.sizeok != Sizeok.none)
7201 return 1;
7203 if (v.aliasTuple)
7205 // If this variable was really a tuple, process each element.
7206 return v.aliasTuple.foreachVar(tv => tv.apply(&func, cast(void*) ad));
7209 if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter))
7210 return 0;
7211 if (!v.isField() || v.semanticRun < PASS.semanticdone)
7212 return 1; // unresolvable forward reference
7214 ad.fields.push(v);
7216 if (v.storage_class & STC.ref_)
7217 return 0;
7218 auto tv = v.type.baseElemOf();
7219 if (auto tvs = tv.isTypeStruct())
7221 if (ad == tvs.sym)
7223 const(char)* psz = (v.type.toBasetype().ty == Tsarray) ? "static array of " : "";
7224 .error(ad.loc, "%s `%s` cannot have field `%s` with %ssame struct type", ad.kind, ad.toPrettyChars, v.toChars(), psz);
7225 ad.type = Type.terror;
7226 ad.errors = true;
7227 return 1;
7230 return 0;
7233 if (ad.members)
7235 for (size_t i = 0; i < ad.members.length; i++)
7237 auto s = (*ad.members)[i];
7238 if (s.apply(&func, cast(void *)ad))
7240 if (ad.sizeok != Sizeok.none)
7242 // recursive determineFields already finished
7243 return true;
7245 return false;
7250 if (ad.sizeok != Sizeok.done)
7251 ad.sizeok = Sizeok.fwd;
7253 return true;
7256 /// Do an atomic operation (currently tailored to [shared] static ctors|dtors) needs
7257 private CallExp doAtomicOp (string op, Identifier var, Expression arg)
7259 assert(op == "-=" || op == "+=");
7261 Module mod = Module.loadCoreAtomic();
7262 if (!mod)
7263 return null; // core.atomic couldn't be loaded
7265 const loc = Loc.initial;
7267 Objects* tiargs = new Objects(1);
7268 (*tiargs)[0] = new StringExp(loc, op);
7270 Expressions* args = new Expressions(2);
7271 (*args)[0] = new IdentifierExp(loc, var);
7272 (*args)[1] = arg;
7274 auto sc = new ScopeExp(loc, mod);
7275 auto dti = new DotTemplateInstanceExp(
7276 loc, sc, Id.atomicOp, tiargs);
7278 return CallExp.create(loc, dti, args);
7281 /***************************************
7282 * Interpret a `pragma(inline, x)`
7284 * Params:
7285 * loc = location for error messages
7286 * sc = scope for evaluation of argument
7287 * args = pragma arguments
7288 * Returns: corresponding `PINLINE` state
7290 PINLINE evalPragmaInline(Loc loc, Scope* sc, Expressions* args)
7292 if (!args || args.length == 0)
7293 return PINLINE.default_;
7295 if (args && args.length > 1)
7297 .error(loc, "one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) args.length);
7298 args.setDim(1);
7299 (*args)[0] = ErrorExp.get();
7302 Expression e = (*args)[0];
7303 if (!e.type)
7305 sc = sc.startCTFE();
7306 e = e.expressionSemantic(sc);
7307 e = resolveProperties(sc, e);
7308 sc = sc.endCTFE();
7309 e = e.ctfeInterpret();
7310 e = e.toBoolean(sc);
7311 if (e.isErrorExp())
7312 .error(loc, "pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars());
7313 (*args)[0] = e;
7316 const opt = e.toBool();
7317 if (opt.isEmpty())
7318 return PINLINE.default_;
7319 else if (opt.get())
7320 return PINLINE.always;
7321 else
7322 return PINLINE.never;
7325 /***************************************************
7326 * Set up loc for a parse of a mixin. Append the input text to the mixin.
7327 * Params:
7328 * input = mixin text
7329 * loc = location to adjust
7330 * mixinOut = sink for mixin text data
7331 * Returns:
7332 * adjusted loc suitable for Parser
7335 Loc adjustLocForMixin(const(char)[] input, ref const Loc loc, ref Output mixinOut)
7337 Loc result;
7338 if (mixinOut.doOutput)
7340 const lines = mixinOut.bufferLines;
7341 writeMixin(input, loc, mixinOut.bufferLines, *mixinOut.buffer);
7342 result = Loc(mixinOut.name.ptr, lines + 2, loc.charnum);
7344 else if (loc.filename)
7346 /* Create a pseudo-filename for the mixin string, as it may not even exist
7347 * in the source file.
7349 auto len = strlen(loc.filename) + 7 + (loc.linnum).sizeof * 3 + 1;
7350 char* filename = cast(char*)mem.xmalloc(len);
7351 snprintf(filename, len, "%s-mixin-%d", loc.filename, cast(int)loc.linnum);
7352 result = Loc(filename, loc.linnum, loc.charnum);
7354 else
7355 result = loc;
7356 return result;
7359 /**************************************
7360 * Append source code text to output for better debugging.
7361 * Canonicalize line endings.
7362 * Params:
7363 * s = source code text
7364 * loc = location of source code text
7365 * lines = line count to update
7366 * output = sink for output
7368 private void writeMixin(const(char)[] s, ref const Loc loc, ref int lines, ref OutBuffer buf)
7370 buf.writestring("// expansion at ");
7371 buf.writestring(loc.toChars());
7372 buf.writenl();
7374 ++lines;
7376 // write by line to create consistent line endings
7377 size_t lastpos = 0;
7378 for (size_t i = 0; i < s.length; ++i)
7380 // detect LF and CRLF
7381 const c = s[i];
7382 if (c == '\n' || (c == '\r' && i+1 < s.length && s[i+1] == '\n'))
7384 buf.writestring(s[lastpos .. i]);
7385 buf.writenl();
7386 ++lines;
7387 if (c == '\r')
7388 ++i;
7389 lastpos = i + 1;
7393 if(lastpos < s.length)
7394 buf.writestring(s[lastpos .. $]);
7396 if (s.length == 0 || s[$-1] != '\n')
7398 buf.writenl(); // ensure empty line after expansion
7399 ++lines;
7401 buf.writenl();
7402 ++lines;
7406 * Check signature of `pragma(printf)` function, print error if invalid.
7408 * printf/scanf-like functions must be of the form:
7409 * extern (C/C++) T printf([parameters...], const(char)* format, ...);
7410 * or:
7411 * extern (C/C++) T vprintf([parameters...], const(char)* format, va_list);
7413 * Params:
7414 * funcdecl = function to check
7415 * f = function type
7416 * sc = scope
7418 void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope* sc)
7420 static bool isPointerToChar(Parameter p)
7422 if (auto tptr = p.type.isTypePointer())
7424 return tptr.next.ty == Tchar;
7426 return false;
7429 bool isVa_list(Parameter p)
7431 return p.type.equals(target.va_listType(funcdecl.loc, sc));
7434 const nparams = f.parameterList.length;
7435 const p = (funcdecl.printf ? Id.printf : Id.scanf).toChars();
7436 if (!(f.linkage == LINK.c || f.linkage == LINK.cpp))
7438 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have `extern(C)` or `extern(C++)` linkage,"
7439 ~" not `extern(%s)`",
7440 p, funcdecl.toChars(), f.linkage.linkageToChars());
7442 if (f.parameterList.varargs == VarArg.variadic)
7444 if (!(nparams >= 1 && isPointerToChar(f.parameterList[nparams - 1])))
7446 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have"
7447 ~ " signature `%s %s([parameters...], const(char)*, ...)` not `%s`",
7448 p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars(), funcdecl.type.toChars());
7451 else if (f.parameterList.varargs == VarArg.none)
7453 if(!(nparams >= 2 && isPointerToChar(f.parameterList[nparams - 2]) &&
7454 isVa_list(f.parameterList[nparams - 1])))
7455 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have"~
7456 " signature `%s %s([parameters...], const(char)*, va_list)`",
7457 p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars());
7459 else
7461 .error(funcdecl.loc, "`pragma(%s)` function `%s` must have C-style variadic `...` or `va_list` parameter",
7462 p, funcdecl.toChars());
7466 /*********************************************
7467 * Search for ident as member of d.
7468 * Params:
7469 * d = dsymbol where ident is searched for
7470 * loc = location to print for error messages
7471 * ident = identifier to search for
7472 * flags = search options
7473 * Returns:
7474 * null if not found
7476 extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags flags = SearchOpt.all)
7478 scope v = new SearchVisitor(loc, ident, flags);
7479 d.accept(v);
7480 return v.result;
7483 Dsymbol search_correct(Dsymbol d, Identifier ident)
7485 /***************************************************
7486 * Search for symbol with correct spelling.
7488 Dsymbol symbol_search_fp(const(char)[] seed, out int cost)
7490 /* If not in the lexer's string table, it certainly isn't in the symbol table.
7491 * Doing this first is a lot faster.
7493 if (!seed.length)
7494 return null;
7495 Identifier id = Identifier.lookup(seed);
7496 if (!id)
7497 return null;
7498 cost = 0; // all the same cost
7499 Dsymbol s = d;
7500 Module.clearCache();
7501 return s.search(Loc.initial, id, SearchOpt.ignoreErrors);
7504 if (global.gag)
7505 return null; // don't do it for speculative compiles; too time consuming
7506 // search for exact name first
7507 if (auto s = d.search(Loc.initial, ident, SearchOpt.ignoreErrors))
7508 return s;
7510 import dmd.root.speller : speller;
7511 return speller!symbol_search_fp(ident.toString());
7514 private extern(C++) class SearchVisitor : Visitor
7516 alias visit = Visitor.visit;
7518 const Loc loc;
7519 Identifier ident;
7520 SearchOptFlags flags;
7521 Dsymbol result;
7523 this(const ref Loc loc, Identifier ident, SearchOptFlags flags)
7525 this.loc = loc;
7526 this.ident = ident;
7527 this.flags = flags;
7530 void setResult(Dsymbol d)
7532 result = d;
7535 override void visit(Dsymbol d)
7537 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", d, d.toChars(), ident.toChars());
7538 return setResult(null);
7541 override void visit(ScopeDsymbol sds)
7543 //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", sds.toChars(), ident.toChars(), flags);
7544 //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
7546 // Look in symbols declared in this module
7547 if (sds.symtab && !(flags & SearchOpt.importsOnly))
7549 //printf(" look in locals\n");
7550 auto s1 = sds.symtab.lookup(ident);
7551 if (s1)
7553 //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
7554 return setResult(s1);
7557 //printf(" not found in locals\n");
7559 // Look in imported scopes
7560 if (!sds.importedScopes)
7561 return setResult(null);
7563 //printf(" look in imports\n");
7564 Dsymbol s = null;
7565 OverloadSet a = null;
7566 // Look in imported modules
7567 for (size_t i = 0; i < sds.importedScopes.length; i++)
7569 // If private import, don't search it
7570 if ((flags & SearchOpt.ignorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_)
7571 continue;
7572 SearchOptFlags sflags = flags & (SearchOpt.ignoreErrors | SearchOpt.ignoreAmbiguous); // remember these in recursive searches
7573 Dsymbol ss = (*sds.importedScopes)[i];
7574 //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
7576 if (ss.isModule())
7578 if (flags & SearchOpt.localsOnly)
7579 continue;
7581 else // mixin template
7583 if (flags & SearchOpt.importsOnly)
7584 continue;
7586 sflags |= SearchOpt.localsOnly;
7589 /* Don't find private members if ss is a module
7591 Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? SearchOpt.ignorePrivateImports : SearchOpt.all));
7592 import dmd.access : symbolIsVisible;
7593 if (!s2 || !(flags & SearchOpt.ignoreVisibility) && !symbolIsVisible(sds, s2))
7594 continue;
7595 if (!s)
7597 s = s2;
7598 if (s && s.isOverloadSet())
7599 a = sds.mergeOverloadSet(ident, a, s);
7601 else if (s2 && s != s2)
7603 if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
7605 /* After following aliases, we found the same
7606 * symbol, so it's not an ambiguity. But if one
7607 * alias is deprecated or less accessible, prefer
7608 * the other.
7610 if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
7611 s = s2;
7613 else
7615 /* Two imports of the same module should be regarded as
7616 * the same.
7618 Import i1 = s.isImport();
7619 Import i2 = s2.isImport();
7620 if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
7622 /* https://issues.dlang.org/show_bug.cgi?id=8668
7623 * Public selective import adds AliasDeclaration in module.
7624 * To make an overload set, resolve aliases in here and
7625 * get actual overload roots which accessible via s and s2.
7627 s = s.toAlias();
7628 s2 = s2.toAlias();
7629 /* If both s2 and s are overloadable (though we only
7630 * need to check s once)
7633 auto so2 = s2.isOverloadSet();
7634 if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
7636 if (symbolIsVisible(sds, s2))
7638 a = sds.mergeOverloadSet(ident, a, s2);
7640 if (!symbolIsVisible(sds, s))
7641 s = s2;
7642 continue;
7645 /* Two different overflow sets can have the same members
7646 * https://issues.dlang.org/show_bug.cgi?id=16709
7648 auto so = s.isOverloadSet();
7649 if (so && so2)
7651 if (so.a.length == so2.a.length)
7653 foreach (j; 0 .. so.a.length)
7655 if (so.a[j] !is so2.a[j])
7656 goto L1;
7658 continue; // the same
7660 { } // different
7664 if (flags & SearchOpt.ignoreAmbiguous) // if return NULL on ambiguity
7665 return setResult(null);
7667 /* If two imports from C import files, pick first one, as C has global name space
7669 if (s.isCsymbol() && s2.isCsymbol())
7670 continue;
7672 if (!(flags & SearchOpt.ignoreErrors))
7673 ScopeDsymbol.multiplyDefined(loc, s, s2);
7674 break;
7679 if (s)
7681 /* Build special symbol if we had multiple finds
7683 if (a)
7685 if (!s.isOverloadSet())
7686 a = sds.mergeOverloadSet(ident, a, s);
7687 s = a;
7689 //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
7690 return setResult(s);
7692 //printf(" not found in imports\n");
7693 return setResult(null);
7696 override void visit(WithScopeSymbol ws)
7698 //printf("WithScopeSymbol.search(%s)\n", ident.toChars());
7699 if (flags & SearchOpt.importsOnly)
7700 return setResult(null);
7701 // Acts as proxy to the with class declaration
7702 Dsymbol s = null;
7703 Expression eold = null;
7704 for (Expression e = ws.withstate.exp; e && e != eold; e = resolveAliasThis(ws._scope, e, true))
7706 if (auto se = e.isScopeExp())
7708 s = se.sds;
7710 else if (e.isTypeExp())
7712 s = e.type.toDsymbol(null);
7714 else
7716 Type t = e.type.toBasetype();
7717 s = t.toDsymbol(null);
7719 if (s)
7721 s = s.search(loc, ident, flags);
7722 if (s)
7723 return setResult(s);
7725 eold = e;
7727 return setResult(null);
7730 override void visit(ArrayScopeSymbol ass)
7732 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
7733 if (ident != Id.dollar)
7734 return setResult(null);
7736 VarDeclaration* pvar;
7737 Expression ce;
7739 static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
7742 /* $ gives the number of type entries in the type tuple
7744 auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
7745 Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
7746 v._init = new ExpInitializer(Loc.initial, e);
7747 v.storage_class |= STC.temp | STC.static_ | STC.const_;
7748 v.dsymbolSemantic(sc);
7749 return v;
7752 const DYNCAST kind = ass.arrayContent.dyncast();
7753 switch (kind) with (DYNCAST)
7755 case dsymbol:
7756 TupleDeclaration td = cast(TupleDeclaration) ass.arrayContent;
7757 /* $ gives the number of elements in the tuple
7759 auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
7760 Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
7761 v._init = new ExpInitializer(Loc.initial, e);
7762 v.storage_class |= STC.temp | STC.static_ | STC.const_;
7763 v.dsymbolSemantic(ass._scope);
7764 return setResult(v);
7765 case type:
7766 return setResult(dollarFromTypeTuple(loc, cast(TypeTuple) ass.arrayContent, ass._scope));
7767 default:
7768 break;
7770 Expression exp = cast(Expression) ass.arrayContent;
7771 if (auto ie = exp.isIndexExp())
7773 /* array[index] where index is some function of $
7775 pvar = &ie.lengthVar;
7776 ce = ie.e1;
7778 else if (auto se = exp.isSliceExp())
7780 /* array[lwr .. upr] where lwr or upr is some function of $
7782 pvar = &se.lengthVar;
7783 ce = se.e1;
7785 else if (auto ae = exp.isArrayExp())
7787 /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
7788 * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
7790 pvar = &ae.lengthVar;
7791 ce = ae.e1;
7793 else
7795 /* Didn't find $, look in enclosing scope(s).
7797 return setResult(null);
7799 ce = ce.lastComma();
7800 /* If we are indexing into an array that is really a type
7801 * tuple, rewrite this as an index into a type tuple and
7802 * try again.
7804 if (auto te = ce.isTypeExp())
7806 if (auto ttp = te.type.isTypeTuple())
7807 return setResult(dollarFromTypeTuple(loc, ttp, ass._scope));
7809 /* *pvar is lazily initialized, so if we refer to $
7810 * multiple times, it gets set only once.
7812 if (!*pvar) // if not already initialized
7814 /* Create variable v and set it to the value of $
7816 VarDeclaration v;
7817 Type t;
7818 if (auto tupexp = ce.isTupleExp())
7820 /* It is for an expression tuple, so the
7821 * length will be a const.
7823 Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
7824 v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
7825 v.storage_class |= STC.temp | STC.static_ | STC.const_;
7827 else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
7829 // Look for opDollar
7830 assert(exp.op == EXP.array || exp.op == EXP.slice);
7831 AggregateDeclaration ad = isAggregate(t);
7832 assert(ad);
7833 Dsymbol s = ad.search(loc, Id.opDollar);
7834 if (!s) // no dollar exists -- search in higher scope
7835 return setResult(null);
7836 s = s.toAlias();
7837 Expression e = null;
7838 // Check for multi-dimensional opDollar(dim) template.
7839 if (TemplateDeclaration td = s.isTemplateDeclaration())
7841 dinteger_t dim = 0;
7842 if (auto ae = exp.isArrayExp())
7844 dim = ae.currentDimension;
7846 else if (exp.isSliceExp())
7848 dim = 0; // slices are currently always one-dimensional
7850 else
7852 assert(0);
7854 auto tiargs = new Objects();
7855 Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
7856 edim = edim.expressionSemantic(ass._scope);
7857 tiargs.push(edim);
7858 e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
7860 else
7862 /* opDollar exists, but it's not a template.
7863 * This is acceptable ONLY for single-dimension indexing.
7864 * Note that it's impossible to have both template & function opDollar,
7865 * because both take no arguments.
7867 auto ae = exp.isArrayExp();
7868 if (ae && ae.arguments.length != 1)
7870 error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
7871 return setResult(null);
7873 Declaration d = s.isDeclaration();
7874 assert(d);
7875 e = new DotVarExp(loc, ce, d);
7877 e = e.expressionSemantic(ass._scope);
7878 if (!e.type)
7879 error(exp.loc, "`%s` has no value", e.toChars());
7880 t = e.type.toBasetype();
7881 if (t && t.ty == Tfunction)
7882 e = new CallExp(e.loc, e);
7883 v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
7884 v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
7886 else
7888 /* For arrays, $ will either be a compile-time constant
7889 * (in which case its value in set during constant-folding),
7890 * or a variable (in which case an expression is created in
7891 * toir.c).
7894 // https://issues.dlang.org/show_bug.cgi?id=16213
7895 // For static arrays $ is known at compile time,
7896 // so declare it as a manifest constant.
7897 auto tsa = ce.type ? ce.type.isTypeSArray() : null;
7898 if (tsa)
7900 auto e = new ExpInitializer(loc, tsa.dim);
7901 v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
7903 else
7905 auto e = new VoidInitializer(Loc.initial);
7906 e.type = Type.tsize_t;
7907 v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
7908 v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
7911 *pvar = v;
7913 (*pvar).dsymbolSemantic(ass._scope);
7914 return setResult((*pvar));
7918 override void visit(Import imp)
7920 //printf("%s.Import.search(ident = '%s', flags = x%x)\n", imp.toChars(), ident.toChars(), flags);
7921 if (!imp.pkg)
7923 imp.load(null);
7924 imp.mod.importAll(null);
7925 imp.mod.dsymbolSemantic(null);
7927 // Forward it to the package/module
7928 return setResult(imp.pkg.search(loc, ident, flags));
7932 override void visit(Nspace ns)
7934 //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars());
7935 if (ns._scope && !ns.symtab)
7936 dsymbolSemantic(ns, ns._scope);
7938 if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called
7940 if (!(flags & SearchOpt.ignoreErrors))
7941 .error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars());
7942 return setResult(null);
7945 visit(cast(ScopeDsymbol)ns);
7948 override void visit(EnumDeclaration em)
7950 //printf("%s.EnumDeclaration::search('%s')\n", em.toChars(), ident.toChars());
7951 if (em._scope)
7953 // Try one last time to resolve this enum
7954 dsymbolSemantic(em, em._scope);
7957 visit(cast(ScopeDsymbol)em);
7960 override void visit(Package pkg)
7962 //printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags);
7963 flags &= ~cast(int)SearchOpt.localsOnly; // searching an import is always transitive
7964 if (!pkg.isModule() && pkg.mod)
7966 // Prefer full package name.
7967 Dsymbol s = pkg.symtab ? pkg.symtab.lookup(ident) : null;
7968 if (s)
7969 return setResult(s);
7970 //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
7971 return setResult(pkg.mod.search(loc, ident, flags));
7974 visit(cast(ScopeDsymbol)pkg);
7977 override void visit(Module m)
7979 /* Since modules can be circularly referenced,
7980 * need to stop infinite recursive searches.
7981 * This is done with the cache.
7983 //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", m.toChars(), ident.toChars(), flags, m.insearch);
7984 if (m.insearch)
7985 return setResult(null);
7987 /* Qualified module searches always search their imports,
7988 * even if SearchLocalsOnly
7990 if (!(flags & SearchOpt.unqualifiedModule))
7991 flags &= ~(SearchOpt.unqualifiedModule | SearchOpt.localsOnly);
7993 if (m.searchCacheIdent == ident && m.searchCacheFlags == flags)
7995 //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
7996 // toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
7997 return setResult(m.searchCacheSymbol);
8000 uint errors = global.errors;
8002 m.insearch = true;
8003 visit(cast(ScopeDsymbol)m);
8004 Dsymbol s = result;
8005 m.insearch = false;
8007 if (errors == global.errors)
8009 // https://issues.dlang.org/show_bug.cgi?id=10752
8010 // Can cache the result only when it does not cause
8011 // access error so the side-effect should be reproduced in later search.
8012 m.searchCacheIdent = ident;
8013 m.searchCacheSymbol = s;
8014 m.searchCacheFlags = flags;
8016 return setResult(s);
8019 override void visit(Declaration decl)
8021 Dsymbol s = null;
8022 if (decl.type)
8024 s = decl.type.toDsymbol(decl._scope);
8025 if (s)
8026 s = s.search(loc, ident, flags);
8028 return setResult(s);
8031 override void visit(StructDeclaration sd)
8033 //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", sd.toChars(), ident.toChars(), flags);
8034 if (sd._scope && !sd.symtab)
8035 dsymbolSemantic(sd, sd._scope);
8037 if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called
8039 // .stringof is always defined (but may be hidden by some other symbol)
8040 if(ident != Id.stringof && !(flags & SearchOpt.ignoreErrors) && sd.semanticRun < PASS.semanticdone)
8041 .error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars());
8042 return setResult(null);
8045 visit(cast(ScopeDsymbol)sd);
8048 override void visit(ClassDeclaration cd)
8050 //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", cd.toChars(), ident.toChars(), flags);
8051 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
8052 if (cd._scope && cd.baseok < Baseok.semanticdone)
8054 if (!cd.inuse)
8056 // must semantic on base class/interfaces
8057 cd.inuse = true;
8058 dsymbolSemantic(cd, null);
8059 cd.inuse = false;
8063 if (!cd.members || !cd.symtab) // opaque or addMember is not yet done
8065 // .stringof is always defined (but may be hidden by some other symbol)
8066 if (ident != Id.stringof && !(flags & SearchOpt.ignoreErrors) && cd.semanticRun < PASS.semanticdone)
8067 cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
8068 //*(char*)0=0;
8069 return setResult(null);
8072 visit(cast(ScopeDsymbol)cd);
8073 auto s = result;
8075 // don't search imports of base classes
8076 if (flags & SearchOpt.importsOnly)
8077 return setResult(s);
8079 if (s)
8080 return setResult(s);
8082 // Search bases classes in depth-first, left to right order
8083 foreach (b; (*cd.baseclasses)[])
8085 if (!b.sym)
8086 continue;
8088 if (!b.sym.symtab)
8090 cd.classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
8091 continue;
8094 import dmd.access : symbolIsVisible;
8096 s = b.sym.search(loc, ident, flags);
8097 if (!s)
8098 continue;
8099 else if (s == cd) // happens if s is nested in this and derives from this
8100 s = null;
8101 else if (!(flags & SearchOpt.ignoreVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s))
8102 s = null;
8103 else
8104 break;
8107 return setResult(s);
8110 /*************************************
8111 * Set scope for future semantic analysis so we can
8112 * deal better with forward references.
8114 * Params:
8115 * d = dsymbol for which the scope is set
8116 * sc = scope that is used to set the value
8118 extern(C++) void setScope(Dsymbol d, Scope* sc)
8120 scope setScopeVisitor = new SetScopeVisitor(sc);
8121 d.accept(setScopeVisitor);
8124 private extern(C++) class SetScopeVisitor : Visitor
8126 alias visit = typeof(super).visit;
8127 Scope* sc;
8129 this(Scope* sc)
8131 this.sc = sc;
8134 override void visit(Dsymbol d)
8136 //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", d, d.toChars(), sc, sc.stc);
8137 if (!sc.nofree)
8138 sc.setNoFree(); // may need it even after semantic() finishes
8139 d._scope = sc;
8140 if (sc.depdecl)
8141 d.depdecl = sc.depdecl;
8142 if (!d.userAttribDecl)
8143 d.userAttribDecl = sc.userAttribDecl;
8146 override void visit(Import i)
8148 visit(cast(Dsymbol)i);
8149 if (i.aliasdecls.length)
8151 if (!i.mod)
8152 i.importAll(sc);
8154 sc = sc.push(i.mod);
8155 sc.visibility = i.visibility;
8156 foreach (ad; i.aliasdecls)
8157 ad.setScope(sc);
8158 sc = sc.pop();
8162 override void visit(Nspace ns)
8164 visit(cast(Dsymbol)ns);
8165 if (ns.members)
8167 assert(sc);
8168 sc = sc.push(ns);
8169 sc.linkage = LINK.cpp; // namespaces default to C++ linkage
8170 sc.parent = ns;
8171 ns.members.foreachDsymbol(s => s.setScope(sc));
8172 sc.pop();
8176 override void visit(EnumDeclaration ed)
8178 if (ed.semanticRun > PASS.initial)
8179 return;
8180 visit(cast(Dsymbol)ed);
8183 override void visit(AggregateDeclaration ad)
8185 // Might need a scope to resolve forward references. The check for
8186 // semanticRun prevents unnecessary setting of _scope during deferred
8187 // setScope phases for aggregates which already finished semantic().
8188 // See https://issues.dlang.org/show_bug.cgi?id=16607
8189 if (ad.semanticRun < PASS.semanticdone)
8190 visit(cast(Dsymbol)ad);
8193 override void visit(AttribDeclaration atr)
8195 Dsymbols* d = atr.include(sc);
8196 //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d);
8197 if (d)
8199 Scope* sc2 = atr.newScope(sc);
8200 d.foreachDsymbol( s => s.setScope(sc2) );
8201 if (sc2 != sc)
8202 sc2.pop();
8206 override void visit(DeprecatedDeclaration dd)
8208 //printf("DeprecatedDeclaration::setScope() %p\n", this);
8209 if (dd.decl)
8210 visit(cast(Dsymbol)dd); // for forward reference
8211 visit(cast(AttribDeclaration)dd);
8214 override void visit(CPPMangleDeclaration cppmd)
8216 if (cppmd.decl)
8217 visit(cast(Dsymbol)cppmd); // for forward reference
8218 visit(cast(AttribDeclaration)cppmd);
8221 override void visit(AnonDeclaration anond)
8223 if (anond.decl)
8224 visit(cast(Dsymbol)anond); // for forward reference
8225 visit(cast(AttribDeclaration)anond);
8228 override void visit(ConditionalDeclaration condd)
8230 condd.include(sc).foreachDsymbol( s => s.setScope(sc) );
8233 override void visit(StaticIfDeclaration sid)
8235 // do not evaluate condition before semantic pass
8236 // But do set the scope, in case we need it for forward referencing
8237 visit(cast(Dsymbol)sid); // for forward reference
8240 override void visit(StaticForeachDeclaration sfd)
8242 // do not evaluate condition before semantic pass
8243 // But do set the scope, in case we need it for forward referencing
8244 visit(cast(Dsymbol)sfd); // for forward reference
8247 override void visit(MixinDeclaration md)
8249 visit(cast(Dsymbol)md);
8252 override void visit(UserAttributeDeclaration uad)
8254 //printf("UserAttributeDeclaration::setScope() %p\n", this);
8255 if (uad.decl)
8256 visit(cast(Dsymbol)uad);
8257 visit(cast(AttribDeclaration)uad);
8261 extern(C++) void importAll(Dsymbol d, Scope* sc)
8263 scope iav = new ImportAllVisitor(sc);
8264 d.accept(iav);
8267 extern(C++) class ImportAllVisitor : Visitor
8269 alias visit = typeof(super).visit;
8270 Scope* sc;
8272 this(Scope* sc)
8274 this.sc = sc;
8277 override void visit(Dsymbol d) {}
8279 override void visit(Import imp)
8281 if (imp.mod) return; // Already done
8284 * https://issues.dlang.org/show_bug.cgi?id=15525
8286 * Loading the import has failed,
8287 * most likely because of parsing errors.
8288 * Therefore we cannot trust the resulting AST.
8290 if (imp.load(sc))
8292 // https://issues.dlang.org/show_bug.cgi?id=23873
8293 // For imports that are not at module or function level,
8294 // e.g. aggregate level, the import symbol is added to the
8295 // symbol table and later semantic is performed on it.
8296 // This leads to semantic analysis on an malformed AST
8297 // which causes all kinds of segfaults.
8298 // The fix is to note that the module has errors and avoid
8299 // semantic analysis on it.
8300 if(imp.mod)
8301 imp.mod.errors = true;
8302 return;
8305 if (!imp.mod) return; // Failed
8307 if (sc.stc & STC.static_)
8308 imp.isstatic = true;
8309 imp.mod.importAll(null);
8310 imp.mod.checkImportDeprecation(imp.loc, sc);
8311 if (sc.explicitVisibility)
8312 imp.visibility = sc.visibility;
8313 if (!imp.isstatic && !imp.aliasId && !imp.names.length)
8314 sc.scopesym.importScope(imp.mod, imp.visibility);
8315 // Enable access to pkgs/mod as soon as posible, because compiler
8316 // can traverse them before the import gets semantic (Issue: 21501)
8317 if (!imp.aliasId && !imp.names.length)
8318 imp.addPackageAccess(sc.scopesym);
8321 override void visit(Module m)
8323 //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", m, m.toChars(), m.parent);
8324 if (m._scope)
8325 return; // already done
8326 if (m.filetype == FileType.ddoc)
8328 error(m.loc, "%s `%s` is a Ddoc file, cannot import it", m.kind, m.toPrettyChars);
8329 return;
8332 /* Note that modules get their own scope, from scratch.
8333 * This is so regardless of where in the syntax a module
8334 * gets imported, it is unaffected by context.
8335 * Ignore prevsc.
8337 Scope* sc = Scope.createGlobal(m, global.errorSink); // create root scope
8339 if (m.md && m.md.msg)
8340 m.md.msg = semanticString(sc, m.md.msg, "deprecation message");
8342 // Add import of "object", even for the "object" module.
8343 // If it isn't there, some compiler rewrites, like
8344 // classinst == classinst -> .object.opEquals(classinst, classinst)
8345 // would fail inside object.d.
8346 if (m.filetype != FileType.c &&
8347 (m.members.length == 0 ||
8348 (*m.members)[0].ident != Id.object ||
8349 (*m.members)[0].isImport() is null))
8351 auto im = new Import(Loc.initial, null, Id.object, null, 0);
8352 m.members.shift(im);
8354 if (!m.symtab)
8356 // Add all symbols into module's symbol table
8357 m.symtab = new DsymbolTable();
8358 for (size_t i = 0; i < m.members.length; i++)
8360 Dsymbol s = (*m.members)[i];
8361 s.addMember(sc, sc.scopesym);
8364 // anything else should be run after addMember, so version/debug symbols are defined
8365 /* Set scope for the symbols so that if we forward reference
8366 * a symbol, it can possibly be resolved on the spot.
8367 * If this works out well, it can be extended to all modules
8368 * before any semantic() on any of them.
8370 m.setScope(sc); // remember module scope for semantic
8371 for (size_t i = 0; i < m.members.length; i++)
8373 Dsymbol s = (*m.members)[i];
8374 s.setScope(sc);
8376 for (size_t i = 0; i < m.members.length; i++)
8378 Dsymbol s = (*m.members)[i];
8379 s.importAll(sc);
8381 sc = sc.pop();
8382 sc.pop(); // 2 pops because Scope.createGlobal() created 2
8385 override void visit(AttribDeclaration atb)
8387 Dsymbols* d = atb.include(sc);
8388 //printf("\tAttribDeclaration::importAll '%s', d = %p\n", toChars(), d);
8389 if (d)
8391 Scope* sc2 = atb.newScope(sc);
8392 d.foreachDsymbol( s => s.importAll(sc2) );
8393 if (sc2 != sc)
8394 sc2.pop();
8398 // do not evaluate condition before semantic pass
8399 override void visit(StaticIfDeclaration _) {}
8400 // do not evaluate aggregate before semantic pass
8401 override void visit(StaticForeachDeclaration _) {}
8404 extern(C++) void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion)
8406 scope v = new SetFieldOffsetVisitor(ad, fieldState, isunion);
8407 d.accept(v);
8410 private extern(C++) class SetFieldOffsetVisitor : Visitor
8412 alias visit = Visitor.visit;
8414 AggregateDeclaration ad;
8415 FieldState* fieldState;
8416 bool isunion;
8418 this(AggregateDeclaration ad, FieldState* fieldState, bool isunion)
8420 this.ad = ad;
8421 this.fieldState = fieldState;
8422 this.isunion = isunion;
8425 override void visit(Dsymbol d) {}
8427 override void visit(Nspace ns)
8429 //printf("Nspace::setFieldOffset() %s\n", toChars());
8430 if (ns._scope) // if fwd reference
8431 dsymbolSemantic(ns, null); // try to resolve it
8432 ns.members.foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
8435 override void visit(VarDeclaration vd)
8437 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), vd.toChars());
8439 if (vd.aliasTuple)
8441 // If this variable was really a tuple, set the offsets for the tuple fields
8442 vd.aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
8443 return;
8446 if (!vd.isField())
8447 return;
8448 assert(!(vd.storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
8450 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
8452 /* Fields that are tuples appear both as part of TupleDeclarations and
8453 * as members. That means ignore them if they are already a field.
8455 if (vd.offset)
8457 // already a field
8458 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
8459 return;
8461 for (size_t i = 0; i < ad.fields.length; i++)
8463 if (ad.fields[i] == vd)
8465 // already a field
8466 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
8467 return;
8471 // Check for forward referenced types which will fail the size() call
8472 Type t = vd.type.toBasetype();
8473 if (vd.storage_class & STC.ref_)
8475 // References are the size of a pointer
8476 t = Type.tvoidptr;
8478 Type tv = t.baseElemOf();
8479 if (tv.ty == Tstruct)
8481 auto ts = cast(TypeStruct)tv;
8482 assert(ts.sym != ad); // already checked in ad.determineFields()
8483 if (!ts.sym.determineSize(vd.loc))
8485 vd.type = Type.terror;
8486 vd.errors = true;
8487 return;
8491 // List in ad.fields. Even if the type is error, it's necessary to avoid
8492 // pointless error diagnostic "more initializers than fields" on struct literal.
8493 ad.fields.push(vd);
8495 if (t.ty == Terror)
8496 return;
8498 /* If coming after a bit field in progress,
8499 * advance past the field
8501 fieldState.inFlight = false;
8503 const sz = t.size(vd.loc);
8504 assert(sz != SIZE_INVALID && sz < uint.max);
8505 uint memsize = cast(uint)sz; // size of member
8506 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
8507 vd.offset = placeField(
8508 fieldState.offset,
8509 memsize, memalignsize, vd.alignment,
8510 ad.structsize, ad.alignsize,
8511 isunion);
8513 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
8514 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
8517 override void visit(BitFieldDeclaration bfd)
8519 enum log = false;
8520 static if (log)
8522 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), bfd.toChars());
8523 void print(const FieldState* fieldState)
8525 fieldState.print();
8526 printf(" fieldWidth = %d bits\n", bfd.fieldWidth);
8528 print(fieldState);
8531 Type t = bfd.type.toBasetype();
8532 const bool anon = bfd.isAnonymous();
8534 // List in ad.fields. Even if the type is error, it's necessary to avoid
8535 // pointless error diagnostic "more initializers than fields" on struct literal.
8536 if (!anon)
8537 ad.fields.push(bfd);
8539 if (t.ty == Terror)
8540 return;
8542 const sz = t.size(bfd.loc);
8543 assert(sz != SIZE_INVALID && sz < uint.max);
8544 uint memsize = cast(uint)sz; // size of member
8545 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
8546 if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
8548 if (bfd.fieldWidth == 0 && !anon)
8549 error(bfd.loc, "named bit fields cannot have 0 width");
8550 if (bfd.fieldWidth > memsize * 8)
8551 error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth);
8553 const style = target.c.bitFieldStyle;
8555 void startNewField()
8557 if (log) printf("startNewField()\n");
8558 uint alignsize;
8559 if (style == TargetC.BitFieldStyle.Gcc_Clang)
8561 if (bfd.fieldWidth > 32)
8562 alignsize = memalignsize;
8563 else if (bfd.fieldWidth > 16)
8564 alignsize = 4;
8565 else if (bfd.fieldWidth > 8)
8566 alignsize = 2;
8567 else
8568 alignsize = 1;
8570 else
8571 alignsize = memsize; // not memalignsize
8573 uint dummy;
8574 bfd.offset = placeField(
8575 fieldState.offset,
8576 memsize, alignsize, bfd.alignment,
8577 ad.structsize,
8578 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? dummy : ad.alignsize,
8579 isunion);
8581 fieldState.inFlight = true;
8582 fieldState.fieldOffset = bfd.offset;
8583 fieldState.bitOffset = 0;
8584 fieldState.fieldSize = memsize;
8587 if (style == TargetC.BitFieldStyle.Gcc_Clang)
8589 if (bfd.fieldWidth == 0)
8591 if (!isunion)
8593 // Use type of zero width field to align to next field
8594 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
8595 ad.structsize = fieldState.offset;
8598 fieldState.inFlight = false;
8599 return;
8602 if (ad.alignsize == 0)
8603 ad.alignsize = 1;
8604 if (!anon &&
8605 ad.alignsize < memalignsize)
8606 ad.alignsize = memalignsize;
8608 else if (style == TargetC.BitFieldStyle.MS)
8610 if (ad.alignsize == 0)
8611 ad.alignsize = 1;
8612 if (bfd.fieldWidth == 0)
8614 if (fieldState.inFlight && !isunion)
8616 // documentation says align to next int
8617 //const alsz = cast(uint)Type.tint32.size();
8618 const alsz = memsize; // but it really does this
8619 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
8620 ad.structsize = fieldState.offset;
8623 fieldState.inFlight = false;
8624 return;
8627 else if (style == TargetC.BitFieldStyle.DM)
8629 if (anon && bfd.fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
8630 return; // this probably should be a bug in DMC
8631 if (ad.alignsize == 0)
8632 ad.alignsize = 1;
8633 if (bfd.fieldWidth == 0)
8635 if (fieldState.inFlight && !isunion)
8637 const alsz = memsize;
8638 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
8639 ad.structsize = fieldState.offset;
8642 fieldState.inFlight = false;
8643 return;
8647 if (!fieldState.inFlight)
8649 //printf("not in flight\n");
8650 startNewField();
8652 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
8654 // If the bit-field spans more units of alignment than its type,
8655 // start a new field at the next alignment boundary.
8656 if (fieldState.bitOffset == fieldState.fieldSize * 8 &&
8657 fieldState.bitOffset + bfd.fieldWidth > memalignsize * 8)
8659 if (log) printf("more units of alignment than its type\n");
8660 startNewField(); // the bit field is full
8662 else
8664 // if alignment boundary is crossed
8665 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
8666 uint end = start + bfd.fieldWidth;
8667 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
8668 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
8670 if (log) printf("alignment is crossed\n");
8671 startNewField();
8675 else if (style == TargetC.BitFieldStyle.DM ||
8676 style == TargetC.BitFieldStyle.MS)
8678 if (memsize != fieldState.fieldSize ||
8679 fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8)
8681 //printf("new field\n");
8682 startNewField();
8685 else
8686 assert(0);
8688 bfd.offset = fieldState.fieldOffset;
8689 bfd.bitOffset = fieldState.bitOffset;
8691 const pastField = bfd.bitOffset + bfd.fieldWidth;
8692 if (style == TargetC.BitFieldStyle.Gcc_Clang)
8694 auto size = (pastField + 7) / 8;
8695 fieldState.fieldSize = size;
8696 //printf(" offset: %d, size: %d\n", offset, size);
8697 if (isunion)
8699 const newstructsize = bfd.offset + size;
8700 if (newstructsize > ad.structsize)
8701 ad.structsize = newstructsize;
8703 else
8704 ad.structsize = bfd.offset + size;
8706 else
8707 fieldState.fieldSize = memsize;
8708 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
8709 //print(fieldState);
8711 if (!isunion)
8713 fieldState.offset = bfd.offset + fieldState.fieldSize;
8714 fieldState.bitOffset = pastField;
8717 //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
8718 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
8719 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
8722 override void visit(TemplateMixin tm)
8724 //printf("TemplateMixin.setFieldOffset() %s\n", tm.toChars());
8725 if (tm._scope) // if fwd reference
8726 dsymbolSemantic(tm, null); // try to resolve it
8728 tm.members.foreachDsymbol( (s) { s.setFieldOffset(ad, fieldState, isunion); } );
8731 override void visit(AttribDeclaration atd)
8733 atd.include(null).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
8736 override void visit(AnonDeclaration anond)
8738 //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", anond);
8739 if (anond.decl)
8741 /* This works by treating an AnonDeclaration as an aggregate 'member',
8742 * so in order to place that member we need to compute the member's
8743 * size and alignment.
8745 size_t fieldstart = ad.fields.length;
8747 /* Hackishly hijack ad's structsize and alignsize fields
8748 * for use in our fake anon aggregate member.
8750 uint savestructsize = ad.structsize;
8751 uint savealignsize = ad.alignsize;
8752 ad.structsize = 0;
8753 ad.alignsize = 0;
8755 FieldState fs;
8756 anond.decl.foreachDsymbol( (s)
8758 s.setFieldOffset(ad, &fs, anond.isunion);
8759 if (anond.isunion)
8760 fs.offset = 0;
8763 /* https://issues.dlang.org/show_bug.cgi?id=13613
8764 * If the fields in this.members had been already
8765 * added in ad.fields, just update *poffset for the subsequent
8766 * field offset calculation.
8768 if (fieldstart == ad.fields.length)
8770 ad.structsize = savestructsize;
8771 ad.alignsize = savealignsize;
8772 fieldState.offset = ad.structsize;
8773 return;
8776 anond.anonstructsize = ad.structsize;
8777 anond.anonalignsize = ad.alignsize;
8778 ad.structsize = savestructsize;
8779 ad.alignsize = savealignsize;
8781 // 0 sized structs are set to 1 byte
8782 if (anond.anonstructsize == 0)
8784 anond.anonstructsize = 1;
8785 anond.anonalignsize = 1;
8788 assert(anond._scope);
8789 auto alignment = anond._scope.alignment();
8791 /* Given the anon 'member's size and alignment,
8792 * go ahead and place it.
8794 anond.anonoffset = placeField(
8795 fieldState.offset,
8796 anond.anonstructsize, anond.anonalignsize, alignment,
8797 ad.structsize, ad.alignsize,
8798 isunion);
8800 // Add to the anon fields the base offset of this anonymous aggregate
8801 //printf("anon fields, anonoffset = %d\n", anonoffset);
8802 foreach (const i; fieldstart .. ad.fields.length)
8804 VarDeclaration v = ad.fields[i];
8805 //printf("\t[%d] %s %d\n", i, v.toChars(), v.offset);
8806 v.offset += anond.anonoffset;