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