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