]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/declaration.d
d: Merge upstream dmd, druntime 28a3b24c2e, phobos 8ab95ded5.
[thirdparty/gcc.git] / gcc / d / dmd / declaration.d
1 /**
2 * Miscellaneous declarations, including typedef, alias, variable declarations including the
3 * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.
4 *
5 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
6 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
7 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d)
9 * Documentation: https://dlang.org/phobos/dmd_declaration.html
10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/declaration.d
11 */
12
13 module dmd.declaration;
14
15 import core.stdc.stdio;
16 import dmd.aggregate;
17 import dmd.arraytypes;
18 import dmd.astenums;
19 import dmd.attrib;
20 import dmd.ctorflow;
21 import dmd.dclass;
22 import dmd.delegatize;
23 import dmd.dscope;
24 import dmd.dstruct;
25 import dmd.dsymbol;
26 import dmd.dsymbolsem;
27 import dmd.dtemplate;
28 import dmd.errors;
29 import dmd.expression;
30 import dmd.func;
31 import dmd.globals;
32 import dmd.gluelayer;
33 import dmd.id;
34 import dmd.identifier;
35 import dmd.init;
36 import dmd.initsem;
37 import dmd.intrange;
38 import dmd.location;
39 import dmd.mtype;
40 import dmd.common.outbuffer;
41 import dmd.root.rootobject;
42 import dmd.target;
43 import dmd.tokens;
44 import dmd.typesem;
45 import dmd.visitor;
46
47 /************************************
48 * Check to see the aggregate type is nested and its context pointer is
49 * accessible from the current scope.
50 * Returns true if error occurs.
51 */
52 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
53 {
54 Dsymbol sparent = ad.toParentLocal();
55 Dsymbol sparent2 = ad.toParent2();
56 Dsymbol s = sc.func;
57 if (ad.isNested() && s)
58 {
59 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
60 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
61 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
62 if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
63 {
64 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
65 return true;
66 }
67 }
68
69 bool result = false;
70 for (size_t i = iStart; i < ad.fields.length; i++)
71 {
72 VarDeclaration vd = ad.fields[i];
73 Type tb = vd.type.baseElemOf();
74 if (tb.ty == Tstruct)
75 {
76 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
77 }
78 }
79 return result;
80 }
81
82 /***********************************************
83 * Mark variable v as modified if it is inside a constructor that var
84 * is a field in.
85 * Also used to allow immutable globals to be initialized inside a static constructor.
86 * Returns:
87 * true if it's an initialization of v
88 */
89 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
90 {
91 //printf("modifyFieldVar(var = %s)\n", var.toChars());
92 Dsymbol s = sc.func;
93 while (1)
94 {
95 FuncDeclaration fd = null;
96 if (s)
97 fd = s.isFuncDeclaration();
98 if (fd &&
99 ((fd.isCtorDeclaration() && var.isField()) ||
100 ((fd.isStaticCtorDeclaration() || fd.isCrtCtor) && !var.isField())) &&
101 fd.toParentDecl() == var.toParent2() &&
102 (!e1 || e1.op == EXP.this_))
103 {
104 bool result = true;
105
106 var.ctorinit = true;
107 //printf("setting ctorinit\n");
108
109 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
110 {
111 assert(e1);
112 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
113 var.type.needsNested());
114
115 const dim = sc.ctorflow.fieldinit.length;
116 auto ad = fd.isMemberDecl();
117 assert(ad);
118 size_t i;
119 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
120 {
121 if (ad.fields[i] == var)
122 break;
123 }
124 assert(i < dim);
125 auto fieldInit = &sc.ctorflow.fieldinit[i];
126 const fi = fieldInit.csx;
127
128 if (fi & CSX.this_ctor)
129 {
130 if (var.type.isMutable() && e1.type.isMutable())
131 result = false;
132 else
133 {
134 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
135 .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
136 .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
137 }
138 }
139 else if (sc.inLoop || (fi & CSX.label))
140 {
141 if (!mustInit && var.type.isMutable() && e1.type.isMutable())
142 result = false;
143 else
144 {
145 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
146 .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
147 }
148 }
149
150 fieldInit.csx |= CSX.this_ctor;
151 fieldInit.loc = e1.loc;
152 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
153 {
154 foreach (j, v; ad.fields)
155 {
156 if (v is var || !var.isOverlappedWith(v))
157 continue;
158 v.ctorinit = true;
159 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
160 }
161 }
162 }
163 else if (fd != sc.func)
164 {
165 if (var.type.isMutable())
166 result = false;
167 else if (sc.func.fes)
168 {
169 const(char)* p = var.isField() ? "field" : var.kind();
170 .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
171 MODtoChars(var.type.mod), p, var.toChars());
172 }
173 else
174 {
175 const(char)* p = var.isField() ? "field" : var.kind();
176 .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
177 MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
178 }
179 }
180 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
181 var.type.isImmutable())
182 {
183 .error(loc, "%s %s `%s` initialization is not allowed in `static this`",
184 MODtoChars(var.type.mod), var.kind(), var.toChars());
185 errorSupplemental(loc, "Use `shared static this` instead.");
186 }
187 return result;
188 }
189 else
190 {
191 if (s)
192 {
193 s = s.toParentP(var.toParent2());
194 continue;
195 }
196 }
197 break;
198 }
199 return false;
200 }
201
202 /******************************************
203 */
204 extern (C++) void ObjectNotFound(Identifier id)
205 {
206 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
207 fatal();
208 }
209
210 /* Accumulator for successive matches.
211 */
212 struct MatchAccumulator
213 {
214 int count; // number of matches found so far
215 MATCH last = MATCH.nomatch; // match level of lastf
216 FuncDeclaration lastf; // last matching function we found
217 FuncDeclaration nextf; // if ambiguous match, this is the "other" function
218 }
219
220 /***********************************************************
221 */
222 extern (C++) abstract class Declaration : Dsymbol
223 {
224 Type type;
225 Type originalType; // before semantic analysis
226 StorageClass storage_class = STC.undefined_;
227 Visibility visibility;
228 LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
229 short inuse; // used to detect cycles
230
231 ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
232 enum wasRead = 1; // set if AliasDeclaration was read
233 enum ignoreRead = 2; // ignore any reads of AliasDeclaration
234 enum nounderscore = 4; // don't prepend _ to mangled name
235
236 Symbol* isym; // import version of csym
237
238 // overridden symbol with pragma(mangle, "...")
239 const(char)[] mangleOverride;
240
241 final extern (D) this(Identifier ident)
242 {
243 super(ident);
244 visibility = Visibility(Visibility.Kind.undefined);
245 }
246
247 final extern (D) this(const ref Loc loc, Identifier ident)
248 {
249 super(loc, ident);
250 visibility = Visibility(Visibility.Kind.undefined);
251 }
252
253 override const(char)* kind() const
254 {
255 return "declaration";
256 }
257
258 override final uinteger_t size(const ref Loc loc)
259 {
260 assert(type);
261 const sz = type.size();
262 if (sz == SIZE_INVALID)
263 errors = true;
264 return sz;
265 }
266
267 /**
268 * Issue an error if an attempt to call a disabled method is made
269 *
270 * If the declaration is disabled but inside a disabled function,
271 * returns `true` but do not issue an error message.
272 *
273 * Params:
274 * loc = Location information of the call
275 * sc = Scope in which the call occurs
276 * isAliasedDeclaration = if `true` searches overload set
277 *
278 * Returns:
279 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
280 */
281 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
282 {
283 if (!(storage_class & STC.disable))
284 return false;
285
286 if (sc.func && sc.func.storage_class & STC.disable)
287 return true;
288
289 if (auto p = toParent())
290 {
291 if (auto postblit = isPostBlitDeclaration())
292 {
293 /* https://issues.dlang.org/show_bug.cgi?id=21885
294 *
295 * If the generated postblit is disabled, it
296 * means that one of the fields has a disabled
297 * postblit. Print the first field that has
298 * a disabled postblit.
299 */
300 if (postblit.isGenerated())
301 {
302 auto sd = p.isStructDeclaration();
303 assert(sd);
304 for (size_t i = 0; i < sd.fields.length; i++)
305 {
306 auto structField = sd.fields[i];
307 if (structField.overlapped)
308 continue;
309 Type tv = structField.type.baseElemOf();
310 if (tv.ty != Tstruct)
311 continue;
312 auto sdv = (cast(TypeStruct)tv).sym;
313 if (!sdv.postblit)
314 continue;
315 if (sdv.postblit.isDisabled())
316 {
317 p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
318 return true;
319 }
320 }
321 }
322 p.error(loc, "is not copyable because it has a disabled postblit");
323 return true;
324 }
325 }
326
327 // if the function is @disabled, maybe there
328 // is an overload in the overload set that isn't
329 if (isAliasedDeclaration)
330 {
331 FuncDeclaration fd = isFuncDeclaration();
332 if (fd)
333 {
334 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
335 if (!(ovl.storage_class & STC.disable))
336 return false;
337 }
338 }
339
340 if (auto ctor = isCtorDeclaration())
341 {
342 if (ctor.isCpCtor && ctor.isGenerated())
343 {
344 .error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
345 return true;
346 }
347 }
348 error(loc, "cannot be used because it is annotated with `@disable`");
349 return true;
350 }
351
352 /*************************************
353 * Check to see if declaration can be modified in this context (sc).
354 * Issue error if not.
355 * Params:
356 * loc = location for error messages
357 * e1 = `null` or `this` expression when this declaration is a field
358 * sc = context
359 * flag = if the first bit is set it means do not issue error message for
360 * invalid modification; if the second bit is set, it means that
361 this declaration is a field and a subfield of it is modified.
362 * Returns:
363 * Modifiable.yes or Modifiable.initialization
364 */
365 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
366 {
367 VarDeclaration v = isVarDeclaration();
368 if (v && v.canassign)
369 return Modifiable.initialization;
370
371 if (isParameter() || isResult())
372 {
373 for (Scope* scx = sc; scx; scx = scx.enclosing)
374 {
375 if (scx.func == parent && (scx.flags & SCOPE.contract))
376 {
377 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
378 if (!(flag & ModifyFlags.noError))
379 error(loc, "cannot modify %s `%s` in contract", s, toChars());
380 return Modifiable.initialization; // do not report type related errors
381 }
382 }
383 }
384
385 if (e1 && e1.op == EXP.this_ && isField())
386 {
387 VarDeclaration vthis = e1.isThisExp().var;
388 for (Scope* scx = sc; scx; scx = scx.enclosing)
389 {
390 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
391 {
392 if (!(flag & ModifyFlags.noError))
393 error(loc, "cannot modify parameter `this` in contract");
394 return Modifiable.initialization; // do not report type related errors
395 }
396 }
397 }
398
399 if (v && (v.isCtorinit() || isField()))
400 {
401 // It's only modifiable if inside the right constructor
402 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
403 return Modifiable.initialization;
404 if (flag & ModifyFlags.fieldAssign)
405 return Modifiable.yes;
406 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes;
407 }
408 return Modifiable.yes;
409 }
410
411 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
412 {
413 Dsymbol s = Dsymbol.search(loc, ident, flags);
414 if (!s && type)
415 {
416 s = type.toDsymbol(_scope);
417 if (s)
418 s = s.search(loc, ident, flags);
419 }
420 return s;
421 }
422
423 final bool isStatic() const pure nothrow @nogc @safe
424 {
425 return (storage_class & STC.static_) != 0;
426 }
427
428 /// Returns the linkage, resolving the target-specific `System` one.
429 final LINK resolvedLinkage() const
430 {
431 return _linkage == LINK.system ? target.systemLinkage() : _linkage;
432 }
433
434 bool isDelete()
435 {
436 return false;
437 }
438
439 bool isDataseg()
440 {
441 return false;
442 }
443
444 bool isThreadlocal()
445 {
446 return false;
447 }
448
449 bool isCodeseg() const pure nothrow @nogc @safe
450 {
451 return false;
452 }
453
454 final bool isFinal() const pure nothrow @nogc @safe
455 {
456 return (storage_class & STC.final_) != 0;
457 }
458
459 bool isAbstract()
460 {
461 return (storage_class & STC.abstract_) != 0;
462 }
463
464 final bool isConst() const pure nothrow @nogc @safe
465 {
466 return (storage_class & STC.const_) != 0;
467 }
468
469 final bool isImmutable() const pure nothrow @nogc @safe
470 {
471 return (storage_class & STC.immutable_) != 0;
472 }
473
474 final bool isWild() const pure nothrow @nogc @safe
475 {
476 return (storage_class & STC.wild) != 0;
477 }
478
479 final bool isAuto() const pure nothrow @nogc @safe
480 {
481 return (storage_class & STC.auto_) != 0;
482 }
483
484 final bool isScope() const pure nothrow @nogc @safe
485 {
486 return (storage_class & STC.scope_) != 0;
487 }
488
489 final bool isReturn() const pure nothrow @nogc @safe
490 {
491 return (storage_class & STC.return_) != 0;
492 }
493
494 final bool isSynchronized() const pure nothrow @nogc @safe
495 {
496 return (storage_class & STC.synchronized_) != 0;
497 }
498
499 final bool isParameter() const pure nothrow @nogc @safe
500 {
501 return (storage_class & STC.parameter) != 0;
502 }
503
504 override final bool isDeprecated() const pure nothrow @nogc @safe
505 {
506 return (storage_class & STC.deprecated_) != 0;
507 }
508
509 final bool isDisabled() const pure nothrow @nogc @safe
510 {
511 return (storage_class & STC.disable) != 0;
512 }
513
514 final bool isOverride() const pure nothrow @nogc @safe
515 {
516 return (storage_class & STC.override_) != 0;
517 }
518
519 final bool isResult() const pure nothrow @nogc @safe
520 {
521 return (storage_class & STC.result) != 0;
522 }
523
524 final bool isField() const pure nothrow @nogc @safe
525 {
526 return (storage_class & STC.field) != 0;
527 }
528
529 final bool isIn() const pure nothrow @nogc @safe
530 {
531 return (storage_class & STC.in_) != 0;
532 }
533
534 final bool isOut() const pure nothrow @nogc @safe
535 {
536 return (storage_class & STC.out_) != 0;
537 }
538
539 final bool isRef() const pure nothrow @nogc @safe
540 {
541 return (storage_class & STC.ref_) != 0;
542 }
543
544 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
545 final bool isReference() const pure nothrow @nogc @safe
546 {
547 return (storage_class & (STC.ref_ | STC.out_)) != 0;
548 }
549
550 final bool isFuture() const pure nothrow @nogc @safe
551 {
552 return (storage_class & STC.future) != 0;
553 }
554
555 final extern(D) bool isSystem() const pure nothrow @nogc @safe
556 {
557 return (storage_class & STC.system) != 0;
558 }
559
560 override final Visibility visible() pure nothrow @nogc @safe
561 {
562 return visibility;
563 }
564
565 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
566 {
567 return this;
568 }
569
570 override void accept(Visitor v)
571 {
572 v.visit(this);
573 }
574 }
575
576 /***********************************************************
577 */
578 extern (C++) final class TupleDeclaration : Declaration
579 {
580 Objects* objects;
581 TypeTuple tupletype; // !=null if this is a type tuple
582 bool isexp; // true: expression tuple
583 bool building; // it's growing in AliasAssign semantic
584
585 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
586 {
587 super(loc, ident);
588 this.objects = objects;
589 }
590
591 override TupleDeclaration syntaxCopy(Dsymbol s)
592 {
593 assert(0);
594 }
595
596 override const(char)* kind() const
597 {
598 return "tuple";
599 }
600
601 override Type getType()
602 {
603 /* If this tuple represents a type, return that type
604 */
605
606 //printf("TupleDeclaration::getType() %s\n", toChars());
607 if (isexp || building)
608 return null;
609 if (!tupletype)
610 {
611 /* It's only a type tuple if all the Object's are types
612 */
613 for (size_t i = 0; i < objects.length; i++)
614 {
615 RootObject o = (*objects)[i];
616 if (o.dyncast() != DYNCAST.type)
617 {
618 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
619 return null;
620 }
621 }
622
623 /* We know it's a type tuple, so build the TypeTuple
624 */
625 Types* types = cast(Types*)objects;
626 auto args = new Parameters(objects.length);
627 OutBuffer buf;
628 int hasdeco = 1;
629 for (size_t i = 0; i < types.length; i++)
630 {
631 Type t = (*types)[i];
632 //printf("type = %s\n", t.toChars());
633 version (none)
634 {
635 buf.printf("_%s_%d", ident.toChars(), i);
636 const len = buf.offset;
637 const name = buf.extractSlice().ptr;
638 auto id = Identifier.idPool(name, len);
639 auto arg = new Parameter(STC.in_, t, id, null);
640 }
641 else
642 {
643 auto arg = new Parameter(0, t, null, null, null);
644 }
645 (*args)[i] = arg;
646 if (!t.deco)
647 hasdeco = 0;
648 }
649
650 tupletype = new TypeTuple(args);
651 if (hasdeco)
652 return tupletype.typeSemantic(Loc.initial, null);
653 }
654 return tupletype;
655 }
656
657 override Dsymbol toAlias2()
658 {
659 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
660 for (size_t i = 0; i < objects.length; i++)
661 {
662 RootObject o = (*objects)[i];
663 if (Dsymbol s = isDsymbol(o))
664 {
665 s = s.toAlias2();
666 (*objects)[i] = s;
667 }
668 }
669 return this;
670 }
671
672 override bool needThis()
673 {
674 //printf("TupleDeclaration::needThis(%s)\n", toChars());
675 return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
676 }
677
678 /***********************************************************
679 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
680 * inside VarExp (isexp == true).
681 * Params:
682 * dg = delegate to call for each Dsymbol
683 */
684 extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
685 {
686 assert(isexp);
687 foreach (o; *objects)
688 {
689 if (auto e = o.isExpression())
690 if (auto ve = e.isVarExp())
691 dg(ve.var);
692 }
693 }
694
695 /***********************************************************
696 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
697 * inside VarExp (isexp == true).
698 * If dg returns !=0, stops and returns that value else returns 0.
699 * Params:
700 * dg = delegate to call for each Dsymbol
701 * Returns:
702 * last value returned by dg()
703 */
704 extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
705 {
706 assert(isexp);
707 foreach (o; *objects)
708 {
709 if (auto e = o.isExpression())
710 if (auto ve = e.isVarExp())
711 if(auto ret = dg(ve.var))
712 return ret;
713 }
714 return 0;
715 }
716
717 override inout(TupleDeclaration) isTupleDeclaration() inout
718 {
719 return this;
720 }
721
722 override void accept(Visitor v)
723 {
724 v.visit(this);
725 }
726 }
727
728 /***********************************************************
729 * https://dlang.org/spec/declaration.html#AliasDeclaration
730 */
731 extern (C++) final class AliasDeclaration : Declaration
732 {
733 Dsymbol aliassym; // alias ident = aliassym;
734
735 Dsymbol overnext; // next in overload list
736 Dsymbol _import; // !=null if unresolved internal alias for selective import
737
738 extern (D) this(const ref Loc loc, Identifier ident, Type type)
739 {
740 super(loc, ident);
741 //printf("AliasDeclaration(id = '%s', type = %p)\n", ident.toChars(), type);
742 //printf("type = '%s'\n", type.toChars());
743 this.type = type;
744 assert(type);
745 }
746
747 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
748 {
749 super(loc, ident);
750 //printf("AliasDeclaration(id = '%s', s = %p)\n", ident.toChars(), s);
751 assert(s != this);
752 this.aliassym = s;
753 assert(s);
754 }
755
756 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
757 {
758 return new AliasDeclaration(loc, id, type);
759 }
760
761 override AliasDeclaration syntaxCopy(Dsymbol s)
762 {
763 //printf("AliasDeclaration::syntaxCopy()\n");
764 assert(!s);
765 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
766 sa.comment = comment;
767 sa.storage_class = storage_class;
768 return sa;
769 }
770
771 override bool overloadInsert(Dsymbol s)
772 {
773 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
774 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
775
776 /** Aliases aren't overloadable themselves, but if their Aliasee is
777 * overloadable they are converted to an overloadable Alias (either
778 * FuncAliasDeclaration or OverDeclaration).
779 *
780 * This is done by moving the Aliasee into such an overloadable alias
781 * which is then used to replace the existing Aliasee. The original
782 * Alias (_this_) remains a useless shell.
783 *
784 * This is a horrible mess. It was probably done to avoid replacing
785 * existing AST nodes and references, but it needs a major
786 * simplification b/c it's too complex to maintain.
787 *
788 * A simpler approach might be to merge any colliding symbols into a
789 * simple Overload class (an array) and then later have that resolve
790 * all collisions.
791 */
792 if (semanticRun >= PASS.semanticdone)
793 {
794 /* Semantic analysis is already finished, and the aliased entity
795 * is not overloadable.
796 */
797 if (type)
798 {
799 /*
800 If type has been resolved already we could
801 still be inserting an alias from an import.
802
803 If we are handling an alias then pretend
804 it was inserting and return true, if not then
805 false since we didn't even pretend to insert something.
806 */
807 return this._import && this.equals(s);
808 }
809
810 /* When s is added in member scope by static if, mixin("code") or others,
811 * aliassym is determined already. See the case in: test/compilable/test61.d
812 */
813 auto sa = aliassym.toAlias();
814
815 if (auto td = s.toAlias().isTemplateDeclaration())
816 s = td.funcroot ? td.funcroot : td;
817
818 if (auto fd = sa.isFuncDeclaration())
819 {
820 auto fa = new FuncAliasDeclaration(ident, fd);
821 fa.visibility = visibility;
822 fa.parent = parent;
823 aliassym = fa;
824 return aliassym.overloadInsert(s);
825 }
826 if (auto td = sa.isTemplateDeclaration())
827 {
828 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
829 od.visibility = visibility;
830 od.parent = parent;
831 aliassym = od;
832 return aliassym.overloadInsert(s);
833 }
834 if (auto od = sa.isOverDeclaration())
835 {
836 if (sa.ident != ident || sa.parent != parent)
837 {
838 od = new OverDeclaration(ident, od);
839 od.visibility = visibility;
840 od.parent = parent;
841 aliassym = od;
842 }
843 return od.overloadInsert(s);
844 }
845 if (auto os = sa.isOverloadSet())
846 {
847 if (sa.ident != ident || sa.parent != parent)
848 {
849 os = new OverloadSet(ident, os);
850 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
851 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
852 // ----
853 // module os1;
854 // import a, b;
855 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
856 // ----
857 // module os2;
858 // import a, b;
859 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
860 // ----
861 // module bug;
862 // import os1, os2;
863 // void test() { merged(123); } // should only look at os2.merged
864 //
865 // os.visibility = visibility;
866 os.parent = parent;
867 aliassym = os;
868 }
869 os.push(s);
870 return true;
871 }
872 return false;
873 }
874
875 /* Don't know yet what the aliased symbol is, so assume it can
876 * be overloaded and check later for correctness.
877 */
878 if (overnext)
879 return overnext.overloadInsert(s);
880 if (s is this)
881 return true;
882 overnext = s;
883 return true;
884 }
885
886 override const(char)* kind() const
887 {
888 return "alias";
889 }
890
891 override Type getType()
892 {
893 if (type)
894 return type;
895 return toAlias().getType();
896 }
897
898 override Dsymbol toAlias()
899 {
900 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
901 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
902 assert(this != aliassym);
903 //static int count; if (++count == 10) *(char*)0=0;
904
905 // Reading the AliasDeclaration
906 if (!(adFlags & ignoreRead))
907 adFlags |= wasRead; // can never assign to this AliasDeclaration again
908
909 if (inuse == 1 && type && _scope)
910 {
911 inuse = 2;
912 uint olderrors = global.errors;
913 Dsymbol s = type.toDsymbol(_scope);
914 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
915 if (global.errors != olderrors)
916 goto Lerr;
917 if (s)
918 {
919 s = s.toAlias();
920 if (global.errors != olderrors)
921 goto Lerr;
922 aliassym = s;
923 inuse = 0;
924 }
925 else
926 {
927 Type t = type.typeSemantic(loc, _scope);
928 if (t.ty == Terror)
929 goto Lerr;
930 if (global.errors != olderrors)
931 goto Lerr;
932 //printf("t = %s\n", t.toChars());
933 inuse = 0;
934 }
935 }
936 if (inuse)
937 {
938 error("recursive alias declaration");
939
940 Lerr:
941 // Avoid breaking "recursive alias" state during errors gagged
942 if (global.gag)
943 return this;
944 aliassym = new AliasDeclaration(loc, ident, Type.terror);
945 type = Type.terror;
946 return aliassym;
947 }
948
949 if (semanticRun >= PASS.semanticdone)
950 {
951 // semantic is already done.
952
953 // Do not see aliassym !is null, because of lambda aliases.
954
955 // Do not see type.deco !is null, even so "alias T = const int;` needs
956 // semantic analysis to take the storage class `const` as type qualifier.
957 }
958 else
959 {
960 // stop AliasAssign tuple building
961 if (aliassym)
962 {
963 if (auto td = aliassym.isTupleDeclaration())
964 {
965 if (td.building)
966 {
967 td.building = false;
968 semanticRun = PASS.semanticdone;
969 return td;
970 }
971 }
972 }
973 if (_import && _import._scope)
974 {
975 /* If this is an internal alias for selective/renamed import,
976 * load the module first.
977 */
978 _import.dsymbolSemantic(null);
979 }
980 if (_scope)
981 {
982 aliasSemantic(this, _scope);
983 }
984 }
985
986 inuse = 1;
987 Dsymbol s = aliassym ? aliassym.toAlias() : this;
988 inuse = 0;
989 return s;
990 }
991
992 override Dsymbol toAlias2()
993 {
994 if (inuse)
995 {
996 error("recursive alias declaration");
997 return this;
998 }
999 inuse = 1;
1000 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
1001 inuse = 0;
1002 return s;
1003 }
1004
1005 override bool isOverloadable() const
1006 {
1007 // assume overloadable until alias is resolved
1008 return semanticRun < PASS.semanticdone ||
1009 aliassym && aliassym.isOverloadable();
1010 }
1011
1012 override inout(AliasDeclaration) isAliasDeclaration() inout
1013 {
1014 return this;
1015 }
1016
1017 /** Returns: `true` if this instance was created to make a template parameter
1018 visible in the scope of a template body, `false` otherwise */
1019 extern (D) bool isAliasedTemplateParameter() const
1020 {
1021 return !!(storage_class & STC.templateparameter);
1022 }
1023
1024 override void accept(Visitor v)
1025 {
1026 v.visit(this);
1027 }
1028 }
1029
1030 /***********************************************************
1031 */
1032 extern (C++) final class OverDeclaration : Declaration
1033 {
1034 Dsymbol overnext; // next in overload list
1035 Dsymbol aliassym;
1036
1037 extern (D) this(Identifier ident, Dsymbol s)
1038 {
1039 super(ident);
1040 this.aliassym = s;
1041 }
1042
1043 override const(char)* kind() const
1044 {
1045 return "overload alias"; // todo
1046 }
1047
1048 override bool equals(const RootObject o) const
1049 {
1050 if (this == o)
1051 return true;
1052
1053 auto s = isDsymbol(o);
1054 if (!s)
1055 return false;
1056
1057 if (auto od2 = s.isOverDeclaration())
1058 return this.aliassym.equals(od2.aliassym);
1059 return this.aliassym == s;
1060 }
1061
1062 override bool overloadInsert(Dsymbol s)
1063 {
1064 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1065 if (overnext)
1066 return overnext.overloadInsert(s);
1067 if (s == this)
1068 return true;
1069 overnext = s;
1070 return true;
1071 }
1072
1073 override bool isOverloadable() const
1074 {
1075 return true;
1076 }
1077
1078 Dsymbol isUnique()
1079 {
1080 Dsymbol result = null;
1081 overloadApply(aliassym, (Dsymbol s)
1082 {
1083 if (result)
1084 {
1085 result = null;
1086 return 1; // ambiguous, done
1087 }
1088 else
1089 {
1090 result = s;
1091 return 0;
1092 }
1093 });
1094 return result;
1095 }
1096
1097 override inout(OverDeclaration) isOverDeclaration() inout
1098 {
1099 return this;
1100 }
1101
1102 override void accept(Visitor v)
1103 {
1104 v.visit(this);
1105 }
1106 }
1107
1108 /***********************************************************
1109 */
1110 extern (C++) class VarDeclaration : Declaration
1111 {
1112 Initializer _init;
1113 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1114 TupleDeclaration aliasTuple; // when `this` is really a tuple of declarations
1115 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1116 Expression edtor; // if !=null, does the destruction of the variable
1117 IntRange* range; // if !=null, the variable is known to be within the range
1118 VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable
1119
1120 uint endlinnum; // line number of end of scope that this var lives in
1121 uint offset;
1122 uint sequenceNumber; // order the variables are declared
1123 structalign_t alignment;
1124
1125 // When interpreting, these point to the value (NULL if value not determinable)
1126 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1127 enum AdrOnStackNone = ~0u;
1128 uint ctfeAdrOnStack;
1129
1130 // `bool` fields that are compacted into bit fields in a string mixin
1131 private extern (D) static struct BitFields
1132 {
1133 bool isargptr; /// if parameter that _argptr points to
1134 bool ctorinit; /// it has been initialized in a ctor
1135 bool iscatchvar; /// this is the exception object variable in catch() clause
1136 bool isowner; /// this is an Owner, despite it being `scope`
1137 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
1138
1139 /// It is a class that was allocated on the stack
1140 ///
1141 /// This means the var is not rebindable once assigned,
1142 /// and the destructor gets run when it goes out of scope
1143 bool onstack;
1144
1145 bool overlapped; /// if it is a field and has overlapping
1146 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
1147 bool maybeScope; /// allow inferring 'scope' for this variable
1148 bool doNotInferReturn; /// do not infer 'return' for this variable
1149
1150 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
1151 bool isCmacro; /// it is a C macro turned into a C declaration
1152 bool dllImport; /// __declspec(dllimport)
1153 bool dllExport; /// __declspec(dllexport)
1154 version (MARS)
1155 {
1156 bool inClosure; /// is inserted into a GC allocated closure
1157 bool inAlignSection; /// is inserted into an aligned section on stack
1158 }
1159 }
1160
1161 import dmd.common.bitfields : generateBitFields;
1162 mixin(generateBitFields!(BitFields, ushort));
1163
1164 byte canassign; // it can be assigned to
1165 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1166
1167 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1168 in
1169 {
1170 assert(ident);
1171 }
1172 do
1173 {
1174 //printf("VarDeclaration('%s')\n", ident.toChars());
1175 super(loc, ident);
1176 debug
1177 {
1178 if (!type && !_init)
1179 {
1180 //printf("VarDeclaration('%s')\n", ident.toChars());
1181 //*(char*)0=0;
1182 }
1183 }
1184
1185 assert(type || _init);
1186 this.type = type;
1187 this._init = _init;
1188 ctfeAdrOnStack = AdrOnStackNone;
1189 this.storage_class = storage_class;
1190 }
1191
1192 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1193 {
1194 return new VarDeclaration(loc, type, ident, _init, storage_class);
1195 }
1196
1197 override VarDeclaration syntaxCopy(Dsymbol s)
1198 {
1199 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1200 assert(!s);
1201 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1202 v.comment = comment;
1203 return v;
1204 }
1205
1206 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1207 {
1208 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1209
1210 if (aliasTuple)
1211 {
1212 // If this variable was really a tuple, set the offsets for the tuple fields
1213 aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
1214 return;
1215 }
1216
1217 if (!isField())
1218 return;
1219 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
1220
1221 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1222
1223 /* Fields that are tuples appear both as part of TupleDeclarations and
1224 * as members. That means ignore them if they are already a field.
1225 */
1226 if (offset)
1227 {
1228 // already a field
1229 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1230 return;
1231 }
1232 for (size_t i = 0; i < ad.fields.length; i++)
1233 {
1234 if (ad.fields[i] == this)
1235 {
1236 // already a field
1237 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1238 return;
1239 }
1240 }
1241
1242 // Check for forward referenced types which will fail the size() call
1243 Type t = type.toBasetype();
1244 if (storage_class & STC.ref_)
1245 {
1246 // References are the size of a pointer
1247 t = Type.tvoidptr;
1248 }
1249 Type tv = t.baseElemOf();
1250 if (tv.ty == Tstruct)
1251 {
1252 auto ts = cast(TypeStruct)tv;
1253 assert(ts.sym != ad); // already checked in ad.determineFields()
1254 if (!ts.sym.determineSize(loc))
1255 {
1256 type = Type.terror;
1257 errors = true;
1258 return;
1259 }
1260 }
1261
1262 // List in ad.fields. Even if the type is error, it's necessary to avoid
1263 // pointless error diagnostic "more initializers than fields" on struct literal.
1264 ad.fields.push(this);
1265
1266 if (t.ty == Terror)
1267 return;
1268
1269 /* If coming after a bit field in progress,
1270 * advance past the field
1271 */
1272 fieldState.inFlight = false;
1273
1274 const sz = t.size(loc);
1275 assert(sz != SIZE_INVALID && sz < uint.max);
1276 uint memsize = cast(uint)sz; // size of member
1277 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1278 offset = AggregateDeclaration.placeField(
1279 &fieldState.offset,
1280 memsize, memalignsize, alignment,
1281 &ad.structsize, &ad.alignsize,
1282 isunion);
1283
1284 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1285 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1286 }
1287
1288 override const(char)* kind() const
1289 {
1290 return "variable";
1291 }
1292
1293 override final inout(AggregateDeclaration) isThis() inout
1294 {
1295 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
1296 {
1297 /* The casting is necessary because `s = s.parent` is otherwise rejected
1298 */
1299 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1300 {
1301 auto ad = (cast(inout)s).isMember();
1302 if (ad)
1303 return ad;
1304 if (!s.parent || !s.parent.isTemplateMixin())
1305 break;
1306 }
1307 }
1308 return null;
1309 }
1310
1311 override final bool needThis()
1312 {
1313 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1314 return isField();
1315 }
1316
1317 override final bool isExport() const
1318 {
1319 return visibility.kind == Visibility.Kind.export_ || dllExport;
1320 }
1321
1322 override final bool isImportedSymbol() const
1323 {
1324 /* If global variable has `export` and `extern` then it is imported
1325 * export int sym1; // definition: exported
1326 * export extern int sym2; // declaration: imported
1327 * export extern int sym3 = 0; // error, extern cannot have initializer
1328 */
1329 bool result =
1330 dllImport ||
1331 visibility.kind == Visibility.Kind.export_ &&
1332 storage_class & STC.extern_ &&
1333 (storage_class & STC.static_ || parent.isModule());
1334 //printf("isImportedSymbol() %s %d\n", toChars(), result);
1335 return result;
1336 }
1337
1338 final bool isCtorinit() const pure nothrow @nogc @safe
1339 {
1340 return setInCtorOnly;
1341 }
1342
1343 /*******************************
1344 * Does symbol go into data segment?
1345 * Includes extern variables.
1346 */
1347 override final bool isDataseg()
1348 {
1349 version (none)
1350 {
1351 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1352 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1353 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1354 printf("parent = '%s'\n", parent.toChars());
1355 }
1356
1357 if (isdataseg == 0) // the value is not cached
1358 {
1359 isdataseg = 2; // The Variables does not go into the datasegment
1360
1361 if (!canTakeAddressOf())
1362 {
1363 return false;
1364 }
1365
1366 Dsymbol parent = toParent();
1367 if (!parent && !(storage_class & STC.static_))
1368 {
1369 error("forward referenced");
1370 type = Type.terror;
1371 }
1372 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
1373 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1374 {
1375 assert(!isParameter() && !isResult());
1376 isdataseg = 1; // It is in the DataSegment
1377 }
1378 }
1379
1380 return (isdataseg == 1);
1381 }
1382 /************************************
1383 * Does symbol go into thread local storage?
1384 */
1385 override final bool isThreadlocal()
1386 {
1387 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1388 /* Data defaults to being thread-local. It is not thread-local
1389 * if it is immutable, const or shared.
1390 */
1391 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1392 //printf("\treturn %d\n", i);
1393 return i;
1394 }
1395
1396 /********************************************
1397 * Can variable be read and written by CTFE?
1398 */
1399 final bool isCTFE()
1400 {
1401 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1402 }
1403
1404 final bool isOverlappedWith(VarDeclaration v)
1405 {
1406 const vsz = v.type.size();
1407 const tsz = type.size();
1408 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1409
1410 // Overlap is checked by comparing bit offsets
1411 auto bitoffset = offset * 8;
1412 auto vbitoffset = v.offset * 8;
1413
1414 // Bitsize of types are overridden by any bit-field widths.
1415 ulong tbitsize = void;
1416 if (auto bf = isBitFieldDeclaration())
1417 {
1418 bitoffset += bf.bitOffset;
1419 tbitsize = bf.fieldWidth;
1420 }
1421 else
1422 tbitsize = tsz * 8;
1423
1424 ulong vbitsize = void;
1425 if (auto vbf = v.isBitFieldDeclaration())
1426 {
1427 vbitoffset += vbf.bitOffset;
1428 vbitsize = vbf.fieldWidth;
1429 }
1430 else
1431 vbitsize = vsz * 8;
1432
1433 return bitoffset < vbitoffset + vbitsize &&
1434 vbitoffset < bitoffset + tbitsize;
1435 }
1436
1437 override final bool hasPointers()
1438 {
1439 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1440 return (!isDataseg() && type.hasPointers());
1441 }
1442
1443 /*************************************
1444 * Return true if we can take the address of this variable.
1445 */
1446 final bool canTakeAddressOf()
1447 {
1448 return !(storage_class & STC.manifest);
1449 }
1450
1451 /******************************************
1452 * Return true if variable needs to call the destructor.
1453 */
1454 final bool needsScopeDtor()
1455 {
1456 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1457 return edtor && !(storage_class & STC.nodtor);
1458 }
1459
1460 /******************************************
1461 * If a variable has a scope destructor call, return call for it.
1462 * Otherwise, return NULL.
1463 */
1464 extern (D) final Expression callScopeDtor(Scope* sc)
1465 {
1466 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1467
1468 // Destruction of STC.field's is handled by buildDtor()
1469 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1470 {
1471 return null;
1472 }
1473
1474 if (iscatchvar)
1475 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1476
1477 Expression e = null;
1478 // Destructors for structs and arrays of structs
1479 Type tv = type.baseElemOf();
1480 if (tv.ty == Tstruct)
1481 {
1482 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1483 if (!sd.dtor || sd.errors)
1484 return null;
1485
1486 const sz = type.size();
1487 assert(sz != SIZE_INVALID);
1488 if (!sz)
1489 return null;
1490
1491 if (type.toBasetype().ty == Tstruct)
1492 {
1493 // v.__xdtor()
1494 e = new VarExp(loc, this);
1495
1496 /* This is a hack so we can call destructors on const/immutable objects.
1497 * Need to add things like "const ~this()" and "immutable ~this()" to
1498 * fix properly.
1499 */
1500 e.type = e.type.mutableOf();
1501
1502 // Enable calling destructors on shared objects.
1503 // The destructor is always a single, non-overloaded function,
1504 // and must serve both shared and non-shared objects.
1505 e.type = e.type.unSharedOf;
1506
1507 e = new DotVarExp(loc, e, sd.dtor, false);
1508 e = new CallExp(loc, e);
1509 }
1510 else
1511 {
1512 // __ArrayDtor(v[0 .. n])
1513 e = new VarExp(loc, this);
1514
1515 const sdsz = sd.type.size();
1516 assert(sdsz != SIZE_INVALID && sdsz != 0);
1517 const n = sz / sdsz;
1518 SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
1519 new IntegerExp(loc, n, Type.tsize_t));
1520
1521 // Prevent redundant bounds check
1522 se.upperIsInBounds = true;
1523 se.lowerIsLessThanUpper = true;
1524
1525 // This is a hack so we can call destructors on const/immutable objects.
1526 se.type = sd.type.arrayOf();
1527
1528 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
1529 }
1530 return e;
1531 }
1532 // Destructors for classes
1533 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1534 {
1535 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1536 {
1537 /* We can do better if there's a way with onstack
1538 * classes to determine if there's no way the monitor
1539 * could be set.
1540 */
1541 //if (cd.isInterfaceDeclaration())
1542 // error("interface `%s` cannot be scope", cd.toChars());
1543
1544 if (onstack) // if any destructors
1545 {
1546 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1547 if (cd.classKind == ClassKind.cpp)
1548 {
1549 // Don't call non-existant dtor
1550 if (!cd.dtor)
1551 break;
1552
1553 e = new VarExp(loc, this);
1554 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1555 e = new DotVarExp(loc, e, cd.dtor, false);
1556 e = new CallExp(loc, e);
1557 break;
1558 }
1559
1560 // delete this;
1561 Expression ec;
1562 ec = new VarExp(loc, this);
1563 e = new DeleteExp(loc, ec, true);
1564 e.type = Type.tvoid;
1565 break;
1566 }
1567 }
1568 }
1569 return e;
1570 }
1571
1572 /*******************************************
1573 * If variable has a constant expression initializer, get it.
1574 * Otherwise, return null.
1575 */
1576 extern (D) final Expression getConstInitializer(bool needFullType = true)
1577 {
1578 assert(type && _init);
1579
1580 // Ungag errors when not speculative
1581 uint oldgag = global.gag;
1582 if (global.gag)
1583 {
1584 Dsymbol sym = isMember();
1585 if (sym && !sym.isSpeculative())
1586 global.gag = 0;
1587 }
1588
1589 if (_scope)
1590 {
1591 inuse++;
1592 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1593 _scope = null;
1594 inuse--;
1595 }
1596
1597 Expression e = _init.initializerToExpression(needFullType ? type : null);
1598 global.gag = oldgag;
1599 return e;
1600 }
1601
1602 /*******************************************
1603 * Helper function for the expansion of manifest constant.
1604 */
1605 extern (D) final Expression expandInitializer(Loc loc)
1606 {
1607 assert((storage_class & STC.manifest) && _init);
1608
1609 auto e = getConstInitializer();
1610 if (!e)
1611 {
1612 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1613 return ErrorExp.get();
1614 }
1615
1616 e = e.copy();
1617 e.loc = loc; // for better error message
1618 return e;
1619 }
1620
1621 override final void checkCtorConstInit()
1622 {
1623 version (none)
1624 {
1625 /* doesn't work if more than one static ctor */
1626 if (ctorinit == 0 && isCtorinit() && !isField())
1627 error("missing initializer in static constructor for const variable");
1628 }
1629 }
1630
1631 /************************************
1632 * Check to see if this variable is actually in an enclosing function
1633 * rather than the current one.
1634 * Update nestedrefs[], closureVars[] and outerVars[].
1635 * Returns: true if error occurs.
1636 */
1637 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1638 {
1639 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1640 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1641 return false;
1642 if (!parent || parent == sc.parent)
1643 return false;
1644 if (isDataseg() || (storage_class & STC.manifest))
1645 return false;
1646
1647 // The current function
1648 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1649 if (!fdthis)
1650 return false; // out of function scope
1651
1652 Dsymbol p = toParent2();
1653
1654 // Function literals from fdthis to p must be delegates
1655 ensureStaticLinkTo(fdthis, p);
1656
1657 // The function that this variable is in
1658 FuncDeclaration fdv = p.isFuncDeclaration();
1659 if (!fdv || fdv == fdthis)
1660 return false;
1661
1662 // Add fdthis to nestedrefs[] if not already there
1663 if (!nestedrefs.contains(fdthis))
1664 nestedrefs.push(fdthis);
1665
1666 //printf("\tfdv = %s\n", fdv.toChars());
1667 //printf("\tfdthis = %s\n", fdthis.toChars());
1668 if (loc.isValid())
1669 {
1670 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1671 return true;
1672 }
1673
1674 // Add this VarDeclaration to fdv.closureVars[] if not already there
1675 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1676 // https://issues.dlang.org/show_bug.cgi?id=17605
1677 (fdv.skipCodegen || !fdthis.skipCodegen))
1678 {
1679 if (!fdv.closureVars.contains(this))
1680 fdv.closureVars.push(this);
1681 }
1682
1683 if (!fdthis.outerVars.contains(this))
1684 fdthis.outerVars.push(this);
1685
1686 //printf("fdthis is %s\n", fdthis.toChars());
1687 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1688 // __dollar creates problems because it isn't a real variable
1689 // https://issues.dlang.org/show_bug.cgi?id=3326
1690 if (ident == Id.dollar)
1691 {
1692 .error(loc, "cannnot use `$` inside a function literal");
1693 return true;
1694 }
1695 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1696 {
1697 ExpInitializer ez = _init.isExpInitializer();
1698 assert(ez);
1699 Expression e = ez.exp;
1700 if (e.op == EXP.construct || e.op == EXP.blit)
1701 e = (cast(AssignExp)e).e2;
1702 return lambdaCheckForNestedRef(e, sc);
1703 }
1704
1705 return false;
1706 }
1707
1708 override final Dsymbol toAlias()
1709 {
1710 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1711 if ((!type || !type.deco) && _scope)
1712 dsymbolSemantic(this, _scope);
1713
1714 assert(this != aliasTuple);
1715 Dsymbol s = aliasTuple ? aliasTuple.toAlias() : this;
1716 return s;
1717 }
1718
1719 // Eliminate need for dynamic_cast
1720 override final inout(VarDeclaration) isVarDeclaration() inout
1721 {
1722 return this;
1723 }
1724
1725 override void accept(Visitor v)
1726 {
1727 v.visit(this);
1728 }
1729 }
1730
1731 /*******************************************************
1732 * C11 6.7.2.1-4 bit fields
1733 */
1734 extern (C++) class BitFieldDeclaration : VarDeclaration
1735 {
1736 Expression width;
1737
1738 uint fieldWidth;
1739 uint bitOffset;
1740
1741 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1742 {
1743 super(loc, type, ident, null);
1744
1745 this.width = width;
1746 this.storage_class |= STC.field;
1747 }
1748
1749 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1750 {
1751 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1752 assert(!s);
1753 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1754 bf.comment = comment;
1755 return bf;
1756 }
1757
1758 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1759 {
1760 return this;
1761 }
1762
1763 override void accept(Visitor v)
1764 {
1765 v.visit(this);
1766 }
1767
1768 /***********************************
1769 * Retrieve the .min or .max values.
1770 * Only valid after semantic analysis.
1771 * Params:
1772 * id = Id.min or Id.max
1773 * Returns:
1774 * the min or max value
1775 */
1776 final ulong getMinMax(Identifier id)
1777 {
1778 const width = fieldWidth;
1779 const uns = type.isunsigned();
1780 const min = id == Id.min;
1781 ulong v;
1782 assert(width != 0); // should have been rejected in semantic pass
1783 if (width == ulong.sizeof * 8)
1784 v = uns ? (min ? ulong.min : ulong.max)
1785 : (min ? long.min : long.max);
1786 else
1787 v = uns ? (min ? 0
1788 : (1L << width) - 1)
1789 : (min ? -(1L << (width - 1))
1790 : (1L << (width - 1)) - 1);
1791 return v;
1792 }
1793
1794 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1795 {
1796 enum log = false;
1797 static if (log)
1798 {
1799 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1800 void print(const ref FieldState fieldState)
1801 {
1802 printf("FieldState.offset = %d bytes\n", fieldState.offset);
1803 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
1804 printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
1805 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
1806 printf(" .inFlight = %d\n", fieldState.inFlight);
1807 printf(" fieldWidth = %d bits\n", fieldWidth);
1808 }
1809 print(fieldState);
1810 }
1811
1812 Type t = type.toBasetype();
1813 const bool anon = isAnonymous();
1814
1815 // List in ad.fields. Even if the type is error, it's necessary to avoid
1816 // pointless error diagnostic "more initializers than fields" on struct literal.
1817 if (!anon)
1818 ad.fields.push(this);
1819
1820 if (t.ty == Terror)
1821 return;
1822
1823 const sz = t.size(loc);
1824 assert(sz != SIZE_INVALID && sz < uint.max);
1825 uint memsize = cast(uint)sz; // size of member
1826 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1827 if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
1828
1829 if (fieldWidth == 0 && !anon)
1830 error(loc, "named bit fields cannot have 0 width");
1831 if (fieldWidth > memsize * 8)
1832 error(loc, "bit field width %d is larger than type", fieldWidth);
1833
1834 const style = target.c.bitFieldStyle;
1835
1836 void startNewField()
1837 {
1838 if (log) printf("startNewField()\n");
1839 uint alignsize;
1840 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1841 {
1842 if (fieldWidth > 32)
1843 alignsize = memalignsize;
1844 else if (fieldWidth > 16)
1845 alignsize = 4;
1846 else if (fieldWidth > 8)
1847 alignsize = 2;
1848 else
1849 alignsize = 1;
1850 }
1851 else
1852 alignsize = memsize; // not memalignsize
1853
1854 uint dummy;
1855 offset = AggregateDeclaration.placeField(
1856 &fieldState.offset,
1857 memsize, alignsize, alignment,
1858 &ad.structsize,
1859 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1860 isunion);
1861
1862 fieldState.inFlight = true;
1863 fieldState.fieldOffset = offset;
1864 fieldState.bitOffset = 0;
1865 fieldState.fieldSize = memsize;
1866 }
1867
1868 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1869 {
1870 if (fieldWidth == 0)
1871 {
1872 if (!isunion)
1873 {
1874 // Use type of zero width field to align to next field
1875 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
1876 ad.structsize = fieldState.offset;
1877 }
1878
1879 fieldState.inFlight = false;
1880 return;
1881 }
1882
1883 if (ad.alignsize == 0)
1884 ad.alignsize = 1;
1885 if (!anon &&
1886 ad.alignsize < memalignsize)
1887 ad.alignsize = memalignsize;
1888 }
1889 else if (style == TargetC.BitFieldStyle.MS)
1890 {
1891 if (ad.alignsize == 0)
1892 ad.alignsize = 1;
1893 if (fieldWidth == 0)
1894 {
1895 if (fieldState.inFlight && !isunion)
1896 {
1897 // documentation says align to next int
1898 //const alsz = cast(uint)Type.tint32.size();
1899 const alsz = memsize; // but it really does this
1900 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1901 ad.structsize = fieldState.offset;
1902 }
1903
1904 fieldState.inFlight = false;
1905 return;
1906 }
1907 }
1908 else if (style == TargetC.BitFieldStyle.DM)
1909 {
1910 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1911 return; // this probably should be a bug in DMC
1912 if (ad.alignsize == 0)
1913 ad.alignsize = 1;
1914 if (fieldWidth == 0)
1915 {
1916 if (fieldState.inFlight && !isunion)
1917 {
1918 const alsz = memsize;
1919 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1920 ad.structsize = fieldState.offset;
1921 }
1922
1923 fieldState.inFlight = false;
1924 return;
1925 }
1926 }
1927
1928 if (!fieldState.inFlight)
1929 {
1930 //printf("not in flight\n");
1931 startNewField();
1932 }
1933 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1934 {
1935 // If the bit-field spans more units of alignment than its type,
1936 // start a new field at the next alignment boundary.
1937 if (fieldState.bitOffset == fieldState.fieldSize * 8 &&
1938 fieldState.bitOffset + fieldWidth > memalignsize * 8)
1939 {
1940 if (log) printf("more units of alignment than its type\n");
1941 startNewField(); // the bit field is full
1942 }
1943 else
1944 {
1945 // if alignment boundary is crossed
1946 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
1947 uint end = start + fieldWidth;
1948 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1949 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
1950 {
1951 if (log) printf("alignment is crossed\n");
1952 startNewField();
1953 }
1954 }
1955 }
1956 else if (style == TargetC.BitFieldStyle.DM ||
1957 style == TargetC.BitFieldStyle.MS)
1958 {
1959 if (memsize != fieldState.fieldSize ||
1960 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1961 {
1962 //printf("new field\n");
1963 startNewField();
1964 }
1965 }
1966 else
1967 assert(0);
1968
1969 offset = fieldState.fieldOffset;
1970 bitOffset = fieldState.bitOffset;
1971
1972 const pastField = bitOffset + fieldWidth;
1973 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1974 {
1975 auto size = (pastField + 7) / 8;
1976 fieldState.fieldSize = size;
1977 //printf(" offset: %d, size: %d\n", offset, size);
1978 ad.structsize = offset + size;
1979 }
1980 else
1981 fieldState.fieldSize = memsize;
1982 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1983 //print(fieldState);
1984
1985 if (!isunion)
1986 {
1987 fieldState.offset = offset + fieldState.fieldSize;
1988 fieldState.bitOffset = pastField;
1989 }
1990
1991 //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
1992 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1993 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1994 }
1995 }
1996
1997 /***********************************************************
1998 * This is a shell around a back end symbol
1999 */
2000 extern (C++) final class SymbolDeclaration : Declaration
2001 {
2002 AggregateDeclaration dsym;
2003
2004 extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
2005 {
2006 super(loc, dsym.ident);
2007 this.dsym = dsym;
2008 storage_class |= STC.const_;
2009 }
2010
2011 // Eliminate need for dynamic_cast
2012 override inout(SymbolDeclaration) isSymbolDeclaration() inout
2013 {
2014 return this;
2015 }
2016
2017 override void accept(Visitor v)
2018 {
2019 v.visit(this);
2020 }
2021 }
2022
2023 /***********************************************************
2024 */
2025 extern (C++) class TypeInfoDeclaration : VarDeclaration
2026 {
2027 Type tinfo;
2028
2029 final extern (D) this(Type tinfo)
2030 {
2031 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
2032 this.tinfo = tinfo;
2033 storage_class = STC.static_ | STC.gshared;
2034 visibility = Visibility(Visibility.Kind.public_);
2035 _linkage = LINK.c;
2036 alignment.set(target.ptrsize);
2037 }
2038
2039 static TypeInfoDeclaration create(Type tinfo)
2040 {
2041 return new TypeInfoDeclaration(tinfo);
2042 }
2043
2044 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
2045 {
2046 assert(0); // should never be produced by syntax
2047 }
2048
2049 override final const(char)* toChars() const
2050 {
2051 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
2052 OutBuffer buf;
2053 buf.writestring("typeid(");
2054 buf.writestring(tinfo.toChars());
2055 buf.writeByte(')');
2056 return buf.extractChars();
2057 }
2058
2059 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
2060 {
2061 return this;
2062 }
2063
2064 override void accept(Visitor v)
2065 {
2066 v.visit(this);
2067 }
2068 }
2069
2070 /***********************************************************
2071 */
2072 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
2073 {
2074 extern (D) this(Type tinfo)
2075 {
2076 super(tinfo);
2077 if (!Type.typeinfostruct)
2078 {
2079 ObjectNotFound(Id.TypeInfo_Struct);
2080 }
2081 type = Type.typeinfostruct.type;
2082 }
2083
2084 static TypeInfoStructDeclaration create(Type tinfo)
2085 {
2086 return new TypeInfoStructDeclaration(tinfo);
2087 }
2088
2089 override void accept(Visitor v)
2090 {
2091 v.visit(this);
2092 }
2093 }
2094
2095 /***********************************************************
2096 */
2097 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
2098 {
2099 extern (D) this(Type tinfo)
2100 {
2101 super(tinfo);
2102 if (!Type.typeinfoclass)
2103 {
2104 ObjectNotFound(Id.TypeInfo_Class);
2105 }
2106 type = Type.typeinfoclass.type;
2107 }
2108
2109 static TypeInfoClassDeclaration create(Type tinfo)
2110 {
2111 return new TypeInfoClassDeclaration(tinfo);
2112 }
2113
2114 override void accept(Visitor v)
2115 {
2116 v.visit(this);
2117 }
2118 }
2119
2120 /***********************************************************
2121 */
2122 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2123 {
2124 extern (D) this(Type tinfo)
2125 {
2126 super(tinfo);
2127 if (!Type.typeinfointerface)
2128 {
2129 ObjectNotFound(Id.TypeInfo_Interface);
2130 }
2131 type = Type.typeinfointerface.type;
2132 }
2133
2134 static TypeInfoInterfaceDeclaration create(Type tinfo)
2135 {
2136 return new TypeInfoInterfaceDeclaration(tinfo);
2137 }
2138
2139 override void accept(Visitor v)
2140 {
2141 v.visit(this);
2142 }
2143 }
2144
2145 /***********************************************************
2146 */
2147 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2148 {
2149 extern (D) this(Type tinfo)
2150 {
2151 super(tinfo);
2152 if (!Type.typeinfopointer)
2153 {
2154 ObjectNotFound(Id.TypeInfo_Pointer);
2155 }
2156 type = Type.typeinfopointer.type;
2157 }
2158
2159 static TypeInfoPointerDeclaration create(Type tinfo)
2160 {
2161 return new TypeInfoPointerDeclaration(tinfo);
2162 }
2163
2164 override void accept(Visitor v)
2165 {
2166 v.visit(this);
2167 }
2168 }
2169
2170 /***********************************************************
2171 */
2172 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2173 {
2174 extern (D) this(Type tinfo)
2175 {
2176 super(tinfo);
2177 if (!Type.typeinfoarray)
2178 {
2179 ObjectNotFound(Id.TypeInfo_Array);
2180 }
2181 type = Type.typeinfoarray.type;
2182 }
2183
2184 static TypeInfoArrayDeclaration create(Type tinfo)
2185 {
2186 return new TypeInfoArrayDeclaration(tinfo);
2187 }
2188
2189 override void accept(Visitor v)
2190 {
2191 v.visit(this);
2192 }
2193 }
2194
2195 /***********************************************************
2196 */
2197 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2198 {
2199 extern (D) this(Type tinfo)
2200 {
2201 super(tinfo);
2202 if (!Type.typeinfostaticarray)
2203 {
2204 ObjectNotFound(Id.TypeInfo_StaticArray);
2205 }
2206 type = Type.typeinfostaticarray.type;
2207 }
2208
2209 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2210 {
2211 return new TypeInfoStaticArrayDeclaration(tinfo);
2212 }
2213
2214 override void accept(Visitor v)
2215 {
2216 v.visit(this);
2217 }
2218 }
2219
2220 /***********************************************************
2221 */
2222 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2223 {
2224 extern (D) this(Type tinfo)
2225 {
2226 super(tinfo);
2227 if (!Type.typeinfoassociativearray)
2228 {
2229 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2230 }
2231 type = Type.typeinfoassociativearray.type;
2232 }
2233
2234 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2235 {
2236 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2237 }
2238
2239 override void accept(Visitor v)
2240 {
2241 v.visit(this);
2242 }
2243 }
2244
2245 /***********************************************************
2246 */
2247 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2248 {
2249 extern (D) this(Type tinfo)
2250 {
2251 super(tinfo);
2252 if (!Type.typeinfoenum)
2253 {
2254 ObjectNotFound(Id.TypeInfo_Enum);
2255 }
2256 type = Type.typeinfoenum.type;
2257 }
2258
2259 static TypeInfoEnumDeclaration create(Type tinfo)
2260 {
2261 return new TypeInfoEnumDeclaration(tinfo);
2262 }
2263
2264 override void accept(Visitor v)
2265 {
2266 v.visit(this);
2267 }
2268 }
2269
2270 /***********************************************************
2271 */
2272 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2273 {
2274 extern (D) this(Type tinfo)
2275 {
2276 super(tinfo);
2277 if (!Type.typeinfofunction)
2278 {
2279 ObjectNotFound(Id.TypeInfo_Function);
2280 }
2281 type = Type.typeinfofunction.type;
2282 }
2283
2284 static TypeInfoFunctionDeclaration create(Type tinfo)
2285 {
2286 return new TypeInfoFunctionDeclaration(tinfo);
2287 }
2288
2289 override void accept(Visitor v)
2290 {
2291 v.visit(this);
2292 }
2293 }
2294
2295 /***********************************************************
2296 */
2297 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2298 {
2299 extern (D) this(Type tinfo)
2300 {
2301 super(tinfo);
2302 if (!Type.typeinfodelegate)
2303 {
2304 ObjectNotFound(Id.TypeInfo_Delegate);
2305 }
2306 type = Type.typeinfodelegate.type;
2307 }
2308
2309 static TypeInfoDelegateDeclaration create(Type tinfo)
2310 {
2311 return new TypeInfoDelegateDeclaration(tinfo);
2312 }
2313
2314 override void accept(Visitor v)
2315 {
2316 v.visit(this);
2317 }
2318 }
2319
2320 /***********************************************************
2321 */
2322 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2323 {
2324 extern (D) this(Type tinfo)
2325 {
2326 super(tinfo);
2327 if (!Type.typeinfotypelist)
2328 {
2329 ObjectNotFound(Id.TypeInfo_Tuple);
2330 }
2331 type = Type.typeinfotypelist.type;
2332 }
2333
2334 static TypeInfoTupleDeclaration create(Type tinfo)
2335 {
2336 return new TypeInfoTupleDeclaration(tinfo);
2337 }
2338
2339 override void accept(Visitor v)
2340 {
2341 v.visit(this);
2342 }
2343 }
2344
2345 /***********************************************************
2346 */
2347 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2348 {
2349 extern (D) this(Type tinfo)
2350 {
2351 super(tinfo);
2352 if (!Type.typeinfoconst)
2353 {
2354 ObjectNotFound(Id.TypeInfo_Const);
2355 }
2356 type = Type.typeinfoconst.type;
2357 }
2358
2359 static TypeInfoConstDeclaration create(Type tinfo)
2360 {
2361 return new TypeInfoConstDeclaration(tinfo);
2362 }
2363
2364 override void accept(Visitor v)
2365 {
2366 v.visit(this);
2367 }
2368 }
2369
2370 /***********************************************************
2371 */
2372 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2373 {
2374 extern (D) this(Type tinfo)
2375 {
2376 super(tinfo);
2377 if (!Type.typeinfoinvariant)
2378 {
2379 ObjectNotFound(Id.TypeInfo_Invariant);
2380 }
2381 type = Type.typeinfoinvariant.type;
2382 }
2383
2384 static TypeInfoInvariantDeclaration create(Type tinfo)
2385 {
2386 return new TypeInfoInvariantDeclaration(tinfo);
2387 }
2388
2389 override void accept(Visitor v)
2390 {
2391 v.visit(this);
2392 }
2393 }
2394
2395 /***********************************************************
2396 */
2397 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2398 {
2399 extern (D) this(Type tinfo)
2400 {
2401 super(tinfo);
2402 if (!Type.typeinfoshared)
2403 {
2404 ObjectNotFound(Id.TypeInfo_Shared);
2405 }
2406 type = Type.typeinfoshared.type;
2407 }
2408
2409 static TypeInfoSharedDeclaration create(Type tinfo)
2410 {
2411 return new TypeInfoSharedDeclaration(tinfo);
2412 }
2413
2414 override void accept(Visitor v)
2415 {
2416 v.visit(this);
2417 }
2418 }
2419
2420 /***********************************************************
2421 */
2422 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2423 {
2424 extern (D) this(Type tinfo)
2425 {
2426 super(tinfo);
2427 if (!Type.typeinfowild)
2428 {
2429 ObjectNotFound(Id.TypeInfo_Wild);
2430 }
2431 type = Type.typeinfowild.type;
2432 }
2433
2434 static TypeInfoWildDeclaration create(Type tinfo)
2435 {
2436 return new TypeInfoWildDeclaration(tinfo);
2437 }
2438
2439 override void accept(Visitor v)
2440 {
2441 v.visit(this);
2442 }
2443 }
2444
2445 /***********************************************************
2446 */
2447 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2448 {
2449 extern (D) this(Type tinfo)
2450 {
2451 super(tinfo);
2452 if (!Type.typeinfovector)
2453 {
2454 ObjectNotFound(Id.TypeInfo_Vector);
2455 }
2456 type = Type.typeinfovector.type;
2457 }
2458
2459 static TypeInfoVectorDeclaration create(Type tinfo)
2460 {
2461 return new TypeInfoVectorDeclaration(tinfo);
2462 }
2463
2464 override void accept(Visitor v)
2465 {
2466 v.visit(this);
2467 }
2468 }
2469
2470 /***********************************************************
2471 * For the "this" parameter to member functions
2472 */
2473 extern (C++) final class ThisDeclaration : VarDeclaration
2474 {
2475 extern (D) this(const ref Loc loc, Type t)
2476 {
2477 super(loc, t, Id.This, null);
2478 storage_class |= STC.nodtor;
2479 }
2480
2481 override ThisDeclaration syntaxCopy(Dsymbol s)
2482 {
2483 assert(0); // should never be produced by syntax
2484 }
2485
2486 override inout(ThisDeclaration) isThisDeclaration() inout
2487 {
2488 return this;
2489 }
2490
2491 override void accept(Visitor v)
2492 {
2493 v.visit(this);
2494 }
2495 }