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