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-2020 by The D Language Foundation, All Rights Reserved
6
 * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
7
 * License:     $(LINK2 http://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.ctorflow;
19
import dmd.dclass;
20
import dmd.delegatize;
21
import dmd.dscope;
22
import dmd.dstruct;
23
import dmd.dsymbol;
24
import dmd.dsymbolsem;
25
import dmd.dtemplate;
26
import dmd.errors;
27
import dmd.expression;
28
import dmd.func;
29
import dmd.globals;
30
import dmd.id;
31
import dmd.identifier;
32
import dmd.init;
33
import dmd.initsem;
34
import dmd.intrange;
35
import dmd.mtype;
36
import dmd.root.outbuffer;
37
import dmd.root.rootobject;
38
import dmd.target;
39
import dmd.tokens;
40
import dmd.typesem;
41
import dmd.visitor;
42

43
/************************************
44
 * Check to see the aggregate type is nested and its context pointer is
45
 * accessible from the current scope.
46
 * Returns true if error occurs.
47
 */
48
bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
49
{
50 1
    Dsymbol sparent = ad.toParentLocal();
51 1
    Dsymbol sparent2 = ad.toParent2();
52 1
    Dsymbol s = sc.func;
53 1
    if (ad.isNested() && s)
54
    {
55
        //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
56
        //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
57
        //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
58 1
        if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
59
        {
60 1
            error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
61 1
            return true;
62
        }
63
    }
64

65 1
    bool result = false;
66 1
    for (size_t i = iStart; i < ad.fields.dim; i++)
67
    {
68 1
        VarDeclaration vd = ad.fields[i];
69 1
        Type tb = vd.type.baseElemOf();
70 1
        if (tb.ty == Tstruct)
71
        {
72 1
            result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
73
        }
74
    }
75 1
    return result;
76
}
77

78
/***********************************************
79
 * Mark variable v as modified if it is inside a constructor that var
80
 * is a field in.
81
 */
82
bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
83
{
84
    //printf("modifyFieldVar(var = %s)\n", var.toChars());
85 1
    Dsymbol s = sc.func;
86 1
    while (1)
87
    {
88 1
        FuncDeclaration fd = null;
89 1
        if (s)
90 1
            fd = s.isFuncDeclaration();
91 1
        if (fd &&
92 1
            ((var.isField() && (fd.isCtorDeclaration() || fd.isPostBlitDeclaration())) ||
93 1
             (!var.isField() && fd.isStaticCtorDeclaration())) &&
94 1
            fd.toParentDecl() == var.toParent2() &&
95 1
            (!e1 || e1.op == TOK.this_))
96
        {
97 1
            bool result = true;
98

99 1
            if (!fd.isPostBlitDeclaration())
100
            {
101 1
                var.ctorinit = true;
102
                //printf("setting ctorinit\n");
103
            }
104

105 1
            if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
106
            {
107 1
                assert(e1);
108 1
                auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
109 1
                                 var.type.needsNested());
110

111 1
                const dim = sc.ctorflow.fieldinit.length;
112 1
                auto ad = fd.isMemberDecl();
113 1
                assert(ad);
114 1
                size_t i;
115 1
                for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
116
                {
117 1
                    if (ad.fields[i] == var)
118 1
                        break;
119
                }
120 1
                assert(i < dim);
121 1
                auto fieldInit = &sc.ctorflow.fieldinit[i];
122 1
                const fi = fieldInit.csx;
123

124 1
                if (fi & CSX.this_ctor)
125
                {
126 1
                    if (var.type.isMutable() && e1.type.isMutable())
127 1
                        result = false;
128
                    else
129
                    {
130 1
                        const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
131 1
                        .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
132 1
                        .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
133
                    }
134
                }
135 1
                else if (sc.inLoop || (fi & CSX.label))
136
                {
137 1
                    if (!mustInit && var.type.isMutable() && e1.type.isMutable())
138 1
                        result = false;
139
                    else
140
                    {
141 1
                        const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
142 1
                        .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
143
                    }
144
                }
145

146 1
                fieldInit.csx |= CSX.this_ctor;
147 1
                fieldInit.loc = e1.loc;
148 1
                if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
149
                {
150 1
                    foreach (j, v; ad.fields)
151
                    {
152 1
                        if (v is var || !var.isOverlappedWith(v))
153 1
                            continue;
154 1
                        v.ctorinit = true;
155 1
                        sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
156
                    }
157
                }
158
            }
159 1
            else if (fd != sc.func)
160
            {
161 1
                if (var.type.isMutable())
162 1
                    result = false;
163 1
                else if (sc.func.fes)
164
                {
165 1
                    const(char)* p = var.isField() ? "field" : var.kind();
166 1
                    .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
167
                        MODtoChars(var.type.mod), p, var.toChars());
168
                }
169
                else
170
                {
171 1
                    const(char)* p = var.isField() ? "field" : var.kind();
172 1
                    .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
173
                        MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
174
                }
175
            }
176 1
            return result;
177
        }
178
        else
179
        {
180 1
            if (s)
181
            {
182 1
                s = s.toParentP(var.toParent2());
183 1
                continue;
184
            }
185
        }
186 1
        break;
187
    }
188 1
    return false;
189
}
190

191
/******************************************
192
 */
193
extern (C++) void ObjectNotFound(Identifier id)
194
{
195 0
    error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
196 0
    fatal();
197
}
198

199
enum STC : ulong
200
{
201
    undefined_          = 0L,
202
    static_             = (1L << 0),
203
    extern_             = (1L << 1),
204
    const_              = (1L << 2),
205
    final_              = (1L << 3),
206
    abstract_           = (1L << 4),
207
    parameter           = (1L << 5),
208
    field               = (1L << 6),
209
    override_           = (1L << 7),
210
    auto_               = (1L << 8),
211
    synchronized_       = (1L << 9),
212
    deprecated_         = (1L << 10),
213
    in_                 = (1L << 11),   // in parameter
214
    out_                = (1L << 12),   // out parameter
215
    lazy_               = (1L << 13),   // lazy parameter
216
    foreach_            = (1L << 14),   // variable for foreach loop
217
                          //(1L << 15)
218
    variadic            = (1L << 16),   // the 'variadic' parameter in: T foo(T a, U b, V variadic...)
219
    ctorinit            = (1L << 17),   // can only be set inside constructor
220
    templateparameter   = (1L << 18),   // template parameter
221
    scope_              = (1L << 19),
222
    immutable_          = (1L << 20),
223
    ref_                = (1L << 21),
224
    init                = (1L << 22),   // has explicit initializer
225
    manifest            = (1L << 23),   // manifest constant
226
    nodtor              = (1L << 24),   // don't run destructor
227
    nothrow_            = (1L << 25),   // never throws exceptions
228
    pure_               = (1L << 26),   // pure function
229
    tls                 = (1L << 27),   // thread local
230
    alias_              = (1L << 28),   // alias parameter
231
    shared_             = (1L << 29),   // accessible from multiple threads
232
    gshared             = (1L << 30),   // accessible from multiple threads, but not typed as "shared"
233
    wild                = (1L << 31),   // for "wild" type constructor
234
    property            = (1L << 32),
235
    safe                = (1L << 33),
236
    trusted             = (1L << 34),
237
    system              = (1L << 35),
238
    ctfe                = (1L << 36),   // can be used in CTFE, even if it is static
239
    disable             = (1L << 37),   // for functions that are not callable
240
    result              = (1L << 38),   // for result variables passed to out contracts
241
    nodefaultctor       = (1L << 39),   // must be set inside constructor
242
    temp                = (1L << 40),   // temporary variable
243
    rvalue              = (1L << 41),   // force rvalue for variables
244
    nogc                = (1L << 42),   // @nogc
245
    volatile_           = (1L << 43),   // destined for volatile in the back end
246
    return_             = (1L << 44),   // 'return ref' or 'return scope' for function parameters
247
    autoref             = (1L << 45),   // Mark for the already deduced 'auto ref' parameter
248
    inference           = (1L << 46),   // do attribute inference
249
    exptemp             = (1L << 47),   // temporary variable that has lifetime restricted to an expression
250
    maybescope          = (1L << 48),   // parameter might be 'scope'
251
    scopeinferred       = (1L << 49),   // 'scope' has been inferred and should not be part of mangling
252
    future              = (1L << 50),   // introducing new base class function
253
    local               = (1L << 51),   // do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).
254
    returninferred      = (1L << 52),   // 'return' has been inferred and should not be part of mangling
255
    live                = (1L << 53),   // function @live attribute
256

257
    // Group members are mutually exclusive (there can be only one)
258
    safeGroup = STC.safe | STC.trusted | STC.system,
259

260
    /// Group for `in` / `out` / `ref` storage classes on parameter
261
    IOR  = STC.in_ | STC.ref_ | STC.out_,
262

263
    TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild),
264
    FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live |
265
                STC.safeGroup),
266
}
267

268
enum STCStorageClass =
269
    (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ | STC.abstract_ | STC.synchronized_ |
270
     STC.deprecated_ | STC.future | STC.override_ | STC.lazy_ | STC.alias_ | STC.out_ | STC.in_ | STC.manifest |
271
     STC.immutable_ | STC.shared_ | STC.wild | STC.nothrow_ | STC.nogc | STC.pure_ | STC.ref_ | STC.return_ | STC.tls | STC.gshared |
272
     STC.property | STC.safeGroup | STC.disable | STC.local | STC.live);
273

274
/* These storage classes "flow through" to the inner scope of a Dsymbol
275
 */
276
enum STCFlowThruAggregate = STC.safeGroup;    /// for an AggregateDeclaration
277
enum STCFlowThruFunction = ~(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.abstract_ | STC.deprecated_ | STC.override_ |
278
                         STC.TYPECTOR | STC.final_ | STC.tls | STC.gshared | STC.ref_ | STC.return_ | STC.property |
279
                         STC.nothrow_ | STC.pure_ | STC.safe | STC.trusted | STC.system); /// for a FuncDeclaration
280

281
/* Accumulator for successive matches.
282
 */
283
struct MatchAccumulator
284
{
285
    int count;              // number of matches found so far
286
    MATCH last = MATCH.nomatch; // match level of lastf
287
    FuncDeclaration lastf;  // last matching function we found
288
    FuncDeclaration nextf;  // if ambiguous match, this is the "other" function
289
}
290

291
/***********************************************************
292
 */
293
extern (C++) abstract class Declaration : Dsymbol
294
{
295
    Type type;
296
    Type originalType;  // before semantic analysis
297
    StorageClass storage_class = STC.undefined_;
298
    Prot protection;
299
    LINK linkage = LINK.default_;
300
    int inuse;          // used to detect cycles
301

302
    // overridden symbol with pragma(mangle, "...")
303
    const(char)[] mangleOverride;
304

305 1
    final extern (D) this(Identifier ident)
306
    {
307 1
        super(ident);
308 1
        protection = Prot(Prot.Kind.undefined);
309
    }
310

311 1
    final extern (D) this(const ref Loc loc, Identifier ident)
312
    {
313 1
        super(loc, ident);
314 1
        protection = Prot(Prot.Kind.undefined);
315
    }
316

317
    override const(char)* kind() const
318
    {
319 0
        return "declaration";
320
    }
321

322
    override final d_uns64 size(const ref Loc loc)
323
    {
324 0
        assert(type);
325 0
        return type.size();
326
    }
327

328
    /**
329
     * Issue an error if an attempt to call a disabled method is made
330
     *
331
     * If the declaration is disabled but inside a disabled function,
332
     * returns `true` but do not issue an error message.
333
     *
334
     * Params:
335
     *   loc = Location information of the call
336
     *   sc  = Scope in which the call occurs
337
     *   isAliasedDeclaration = if `true` searches overload set
338
     *
339
     * Returns:
340
     *   `true` if this `Declaration` is `@disable`d, `false` otherwise.
341
     */
342
    extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
343
    {
344 1
        if (!(storage_class & STC.disable))
345 1
            return false;
346

347 1
        if (sc.func && sc.func.storage_class & STC.disable)
348 1
            return true;
349

350 1
        auto p = toParent();
351 1
        if (p && isPostBlitDeclaration())
352
        {
353 1
            p.error(loc, "is not copyable because it is annotated with `@disable`");
354 1
            return true;
355
        }
356

357
        // if the function is @disabled, maybe there
358
        // is an overload in the overload set that isn't
359 1
        if (isAliasedDeclaration)
360
        {
361 1
            FuncDeclaration fd = isFuncDeclaration();
362 1
            if (fd)
363
            {
364 1
                for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
365 1
                    if (!(ovl.storage_class & STC.disable))
366 1
                        return false;
367
            }
368
        }
369

370 1
        if (auto ctor = isCtorDeclaration())
371
        {
372 1
            if (ctor.isCpCtor && ctor.generated)
373
            {
374 1
                .error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
375 1
                return true;
376
            }
377
        }
378 1
        error(loc, "cannot be used because it is annotated with `@disable`");
379 1
        return true;
380
    }
381

382
    /*************************************
383
     * Check to see if declaration can be modified in this context (sc).
384
     * Issue error if not.
385
     * Params:
386
     *  loc  = location for error messages
387
     *  e1   = `null` or `this` expression when this declaration is a field
388
     *  sc   = context
389
     *  flag = !=0 means do not issue error message for invalid modification
390
     * Returns:
391
     *  Modifiable.yes or Modifiable.initialization
392
     */
393
    extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, int flag)
394
    {
395 1
        VarDeclaration v = isVarDeclaration();
396 1
        if (v && v.canassign)
397 0
            return Modifiable.initialization;
398

399 1
        if (isParameter() || isResult())
400
        {
401 1
            for (Scope* scx = sc; scx; scx = scx.enclosing)
402
            {
403 1
                if (scx.func == parent && (scx.flags & SCOPE.contract))
404
                {
405 1
                    const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
406 1
                    if (!flag)
407 1
                        error(loc, "cannot modify %s `%s` in contract", s, toChars());
408 1
                    return Modifiable.initialization; // do not report type related errors
409
                }
410
            }
411
        }
412

413 1
        if (e1 && e1.op == TOK.this_ && isField())
414
        {
415 1
            VarDeclaration vthis = (cast(ThisExp)e1).var;
416 1
            for (Scope* scx = sc; scx; scx = scx.enclosing)
417
            {
418 1
                if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
419
                {
420 1
                    if (!flag)
421 1
                        error(loc, "cannot modify parameter 'this' in contract");
422 1
                    return Modifiable.initialization; // do not report type related errors
423
                }
424
            }
425
        }
426

427 1
        if (v && (isCtorinit() || isField()))
428
        {
429
            // It's only modifiable if inside the right constructor
430 1
            if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
431 1
                return Modifiable.initialization;
432 1
            return modifyFieldVar(loc, sc, v, e1)
433 1
                ? Modifiable.initialization : Modifiable.yes;
434
        }
435 1
        return Modifiable.yes;
436
    }
437

438
    override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
439
    {
440 1
        Dsymbol s = Dsymbol.search(loc, ident, flags);
441 1
        if (!s && type)
442
        {
443 1
            s = type.toDsymbol(_scope);
444 1
            if (s)
445 1
                s = s.search(loc, ident, flags);
446
        }
447 1
        return s;
448
    }
449

450
    final bool isStatic() const pure nothrow @nogc @safe
451
    {
452 1
        return (storage_class & STC.static_) != 0;
453
    }
454

455
    bool isDelete()
456
    {
457 1
        return false;
458
    }
459

460
    bool isDataseg()
461
    {
462 1
        return false;
463
    }
464

465
    bool isThreadlocal()
466
    {
467 1
        return false;
468
    }
469

470
    bool isCodeseg() const pure nothrow @nogc @safe
471
    {
472 1
        return false;
473
    }
474

475
    final bool isCtorinit() const pure nothrow @nogc @safe
476
    {
477 1
        return (storage_class & STC.ctorinit) != 0;
478
    }
479

480
    final bool isFinal() const pure nothrow @nogc @safe
481
    {
482 1
        return (storage_class & STC.final_) != 0;
483
    }
484

485
    bool isAbstract()
486
    {
487 1
        return (storage_class & STC.abstract_) != 0;
488
    }
489

490
    final bool isConst() const pure nothrow @nogc @safe
491
    {
492 1
        return (storage_class & STC.const_) != 0;
493
    }
494

495
    final bool isImmutable() const pure nothrow @nogc @safe
496
    {
497 1
        return (storage_class & STC.immutable_) != 0;
498
    }
499

500
    final bool isWild() const pure nothrow @nogc @safe
501
    {
502 1
        return (storage_class & STC.wild) != 0;
503
    }
504

505
    final bool isAuto() const pure nothrow @nogc @safe
506
    {
507 0
        return (storage_class & STC.auto_) != 0;
508
    }
509

510
    final bool isScope() const pure nothrow @nogc @safe
511
    {
512 1
        return (storage_class & STC.scope_) != 0;
513
    }
514

515
    final bool isSynchronized() const pure nothrow @nogc @safe
516
    {
517 1
        return (storage_class & STC.synchronized_) != 0;
518
    }
519

520
    final bool isParameter() const pure nothrow @nogc @safe
521
    {
522 1
        return (storage_class & STC.parameter) != 0;
523
    }
524

525
    override final bool isDeprecated() const pure nothrow @nogc @safe
526
    {
527 1
        return (storage_class & STC.deprecated_) != 0;
528
    }
529

530
    final bool isDisabled() const pure nothrow @nogc @safe
531
    {
532 1
        return (storage_class & STC.disable) != 0;
533
    }
534

535
    final bool isOverride() const pure nothrow @nogc @safe
536
    {
537 1
        return (storage_class & STC.override_) != 0;
538
    }
539

540
    final bool isResult() const pure nothrow @nogc @safe
541
    {
542 1
        return (storage_class & STC.result) != 0;
543
    }
544

545
    final bool isField() const pure nothrow @nogc @safe
546
    {
547 1
        return (storage_class & STC.field) != 0;
548
    }
549

550
    final bool isIn() const pure nothrow @nogc @safe
551
    {
552 0
        return (storage_class & STC.in_) != 0;
553
    }
554

555
    final bool isOut() const pure nothrow @nogc @safe
556
    {
557 1
        return (storage_class & STC.out_) != 0;
558
    }
559

560
    final bool isRef() const pure nothrow @nogc @safe
561
    {
562 1
        return (storage_class & STC.ref_) != 0;
563
    }
564

565
    final bool isFuture() const pure nothrow @nogc @safe
566
    {
567 1
        return (storage_class & STC.future) != 0;
568
    }
569

570
    override final Prot prot() pure nothrow @nogc @safe
571
    {
572 1
        return protection;
573
    }
574

575
    override final inout(Declaration) isDeclaration() inout
576
    {
577 1
        return this;
578
    }
579

580
    override void accept(Visitor v)
581
    {
582 0
        v.visit(this);
583
    }
584
}
585

586
/***********************************************************
587
 */
588
extern (C++) final class TupleDeclaration : Declaration
589
{
590
    Objects* objects;
591
    bool isexp;             // true: expression tuple
592
    TypeTuple tupletype;    // !=null if this is a type tuple
593

594 1
    extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
595
    {
596 1
        super(loc, ident);
597 1
        this.objects = objects;
598
    }
599

600
    override Dsymbol syntaxCopy(Dsymbol s)
601
    {
602 0
        assert(0);
603
    }
604

605
    override const(char)* kind() const
606
    {
607 1
        return "tuple";
608
    }
609

610
    override Type getType()
611
    {
612
        /* If this tuple represents a type, return that type
613
         */
614

615
        //printf("TupleDeclaration::getType() %s\n", toChars());
616 1
        if (isexp)
617 1
            return null;
618 1
        if (!tupletype)
619
        {
620
            /* It's only a type tuple if all the Object's are types
621
             */
622 1
            for (size_t i = 0; i < objects.dim; i++)
623
            {
624 1
                RootObject o = (*objects)[i];
625 1
                if (o.dyncast() != DYNCAST.type)
626
                {
627
                    //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
628 1
                    return null;
629
                }
630
            }
631

632
            /* We know it's a type tuple, so build the TypeTuple
633
             */
634 1
            Types* types = cast(Types*)objects;
635 1
            auto args = new Parameters(objects.dim);
636 1
            OutBuffer buf;
637 1
            int hasdeco = 1;
638 1
            for (size_t i = 0; i < types.dim; i++)
639
            {
640 1
                Type t = (*types)[i];
641
                //printf("type = %s\n", t.toChars());
642
                version (none)
643
                {
644
                    buf.printf("_%s_%d", ident.toChars(), i);
645
                    const len = buf.offset;
646
                    const name = buf.extractSlice().ptr;
647
                    auto id = Identifier.idPool(name, len);
648
                    auto arg = new Parameter(STC.in_, t, id, null);
649
                }
650
                else
651
                {
652 1
                    auto arg = new Parameter(0, t, null, null, null);
653
                }
654 1
                (*args)[i] = arg;
655 1
                if (!t.deco)
656 0
                    hasdeco = 0;
657
            }
658

659 1
            tupletype = new TypeTuple(args);
660 1
            if (hasdeco)
661 1
                return tupletype.typeSemantic(Loc.initial, null);
662
        }
663 1
        return tupletype;
664
    }
665

666
    override Dsymbol toAlias2()
667
    {
668
        //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
669 1
        for (size_t i = 0; i < objects.dim; i++)
670
        {
671 1
            RootObject o = (*objects)[i];
672 1
            if (Dsymbol s = isDsymbol(o))
673
            {
674 1
                s = s.toAlias2();
675 1
                (*objects)[i] = s;
676
            }
677
        }
678 1
        return this;
679
    }
680

681
    override bool needThis()
682
    {
683
        //printf("TupleDeclaration::needThis(%s)\n", toChars());
684 1
        for (size_t i = 0; i < objects.dim; i++)
685
        {
686 1
            RootObject o = (*objects)[i];
687 1
            if (o.dyncast() == DYNCAST.expression)
688
            {
689 1
                Expression e = cast(Expression)o;
690 1
                if (e.op == TOK.dSymbol)
691
                {
692 1
                    DsymbolExp ve = cast(DsymbolExp)e;
693 1
                    Declaration d = ve.s.isDeclaration();
694 1
                    if (d && d.needThis())
695
                    {
696 1
                        return true;
697
                    }
698
                }
699
            }
700
        }
701 1
        return false;
702
    }
703

704
    override inout(TupleDeclaration) isTupleDeclaration() inout
705
    {
706 1
        return this;
707
    }
708

709
    override void accept(Visitor v)
710
    {
711 1
        v.visit(this);
712
    }
713
}
714

715
/***********************************************************
716
 */
717
extern (C++) final class AliasDeclaration : Declaration
718
{
719
    Dsymbol aliassym;
720
    Dsymbol overnext;   // next in overload list
721
    Dsymbol _import;    // !=null if unresolved internal alias for selective import
722

723 1
    extern (D) this(const ref Loc loc, Identifier ident, Type type)
724
    {
725 1
        super(loc, ident);
726
        //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
727
        //printf("type = '%s'\n", type.toChars());
728 1
        this.type = type;
729 1
        assert(type);
730
    }
731

732 1
    extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
733
    {
734 1
        super(loc, ident);
735
        //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
736 1
        assert(s != this);
737 1
        this.aliassym = s;
738 1
        assert(s);
739
    }
740

741
    static AliasDeclaration create(Loc loc, Identifier id, Type type)
742
    {
743 0
        return new AliasDeclaration(loc, id, type);
744
    }
745

746
    override Dsymbol syntaxCopy(Dsymbol s)
747
    {
748
        //printf("AliasDeclaration::syntaxCopy()\n");
749 1
        assert(!s);
750 1
        AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
751 1
        sa.comment = comment;
752 1
        sa.storage_class = storage_class;
753 1
        return sa;
754
    }
755

756
    override bool overloadInsert(Dsymbol s)
757
    {
758
        //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
759
        //       loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
760

761
        /** Aliases aren't overloadable themselves, but if their Aliasee is
762
         *  overloadable they are converted to an overloadable Alias (either
763
         *  FuncAliasDeclaration or OverDeclaration).
764
         *
765
         *  This is done by moving the Aliasee into such an overloadable alias
766
         *  which is then used to replace the existing Aliasee. The original
767
         *  Alias (_this_) remains a useless shell.
768
         *
769
         *  This is a horrible mess. It was probably done to avoid replacing
770
         *  existing AST nodes and references, but it needs a major
771
         *  simplification b/c it's too complex to maintain.
772
         *
773
         *  A simpler approach might be to merge any colliding symbols into a
774
         *  simple Overload class (an array) and then later have that resolve
775
         *  all collisions.
776
         */
777 1
        if (semanticRun >= PASS.semanticdone)
778
        {
779
            /* Semantic analysis is already finished, and the aliased entity
780
             * is not overloadable.
781
             */
782 1
            if (type)
783 1
                return false;
784

785
            /* When s is added in member scope by static if, mixin("code") or others,
786
             * aliassym is determined already. See the case in: test/compilable/test61.d
787
             */
788 1
            auto sa = aliassym.toAlias();
789 1
            if (auto fd = sa.isFuncDeclaration())
790
            {
791 1
                auto fa = new FuncAliasDeclaration(ident, fd);
792 1
                fa.protection = protection;
793 1
                fa.parent = parent;
794 1
                aliassym = fa;
795 1
                return aliassym.overloadInsert(s);
796
            }
797 1
            if (auto td = sa.isTemplateDeclaration())
798
            {
799 1
                auto od = new OverDeclaration(ident, td);
800 1
                od.protection = protection;
801 1
                od.parent = parent;
802 1
                aliassym = od;
803 1
                return aliassym.overloadInsert(s);
804
            }
805 1
            if (auto od = sa.isOverDeclaration())
806
            {
807 1
                if (sa.ident != ident || sa.parent != parent)
808
                {
809 1
                    od = new OverDeclaration(ident, od);
810 1
                    od.protection = protection;
811 1
                    od.parent = parent;
812 1
                    aliassym = od;
813
                }
814 1
                return od.overloadInsert(s);
815
            }
816 1
            if (auto os = sa.isOverloadSet())
817
            {
818 1
                if (sa.ident != ident || sa.parent != parent)
819
                {
820 1
                    os = new OverloadSet(ident, os);
821
                    // TODO: protection is lost here b/c OverloadSets have no protection attribute
822
                    // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
823
                    // ----
824
                    // module os1;
825
                    // import a, b;
826
                    // private alias merged = foo; // private alias to overload set of a.foo and b.foo
827
                    // ----
828
                    // module os2;
829
                    // import a, b;
830
                    // public alias merged = bar; // public alias to overload set of a.bar and b.bar
831
                    // ----
832
                    // module bug;
833
                    // import os1, os2;
834
                    // void test() { merged(123); } // should only look at os2.merged
835
                    //
836
                    // os.protection = protection;
837 1
                    os.parent = parent;
838 1
                    aliassym = os;
839
                }
840 1
                os.push(s);
841 1
                return true;
842
            }
843 1
            return false;
844
        }
845

846
        /* Don't know yet what the aliased symbol is, so assume it can
847
         * be overloaded and check later for correctness.
848
         */
849 1
        if (overnext)
850 1
            return overnext.overloadInsert(s);
851 1
        if (s is this)
852 0
            return true;
853 1
        overnext = s;
854 1
        return true;
855
    }
856

857
    override const(char)* kind() const
858
    {
859 1
        return "alias";
860
    }
861

862
    override Type getType()
863
    {
864 1
        if (type)
865 1
            return type;
866 1
        return toAlias().getType();
867
    }
868

869
    override Dsymbol toAlias()
870
    {
871
        //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
872
        //    loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
873 1
        assert(this != aliassym);
874
        //static int count; if (++count == 10) *(char*)0=0;
875 1
        if (inuse == 1 && type && _scope)
876
        {
877 1
            inuse = 2;
878 1
            uint olderrors = global.errors;
879 1
            Dsymbol s = type.toDsymbol(_scope);
880
            //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
881 1
            if (global.errors != olderrors)
882 1
                goto Lerr;
883 1
            if (s)
884
            {
885 1
                s = s.toAlias();
886 1
                if (global.errors != olderrors)
887 0
                    goto Lerr;
888 1
                aliassym = s;
889 1
                inuse = 0;
890
            }
891
            else
892
            {
893 1
                Type t = type.typeSemantic(loc, _scope);
894 1
                if (t.ty == Terror)
895 1
                    goto Lerr;
896 1
                if (global.errors != olderrors)
897 0
                    goto Lerr;
898
                //printf("t = %s\n", t.toChars());
899 1
                inuse = 0;
900
            }
901
        }
902 1
        if (inuse)
903
        {
904 1
            error("recursive alias declaration");
905

906
        Lerr:
907
            // Avoid breaking "recursive alias" state during errors gagged
908 1
            if (global.gag)
909 1
                return this;
910 1
            aliassym = new AliasDeclaration(loc, ident, Type.terror);
911 1
            type = Type.terror;
912 1
            return aliassym;
913
        }
914

915 1
        if (semanticRun >= PASS.semanticdone)
916
        {
917
            // semantic is already done.
918

919
            // Do not see aliassym !is null, because of lambda aliases.
920

921
            // Do not see type.deco !is null, even so "alias T = const int;` needs
922
            // semantic analysis to take the storage class `const` as type qualifier.
923
        }
924
        else
925
        {
926 1
            if (_import && _import._scope)
927
            {
928
                /* If this is an internal alias for selective/renamed import,
929
                 * load the module first.
930
                 */
931 1
                _import.dsymbolSemantic(null);
932
            }
933 1
            if (_scope)
934
            {
935 1
                aliasSemantic(this, _scope);
936
            }
937
        }
938

939 1
        inuse = 1;
940 1
        Dsymbol s = aliassym ? aliassym.toAlias() : this;
941 1
        inuse = 0;
942 1
        return s;
943
    }
944

945
    override Dsymbol toAlias2()
946
    {
947 1
        if (inuse)
948
        {
949 0
            error("recursive alias declaration");
950 0
            return this;
951
        }
952 1
        inuse = 1;
953 1
        Dsymbol s = aliassym ? aliassym.toAlias2() : this;
954 1
        inuse = 0;
955 1
        return s;
956
    }
957

958
    override bool isOverloadable() const
959
    {
960
        // assume overloadable until alias is resolved
961 1
        return semanticRun < PASS.semanticdone ||
962 1
            aliassym && aliassym.isOverloadable();
963
    }
964

965
    override inout(AliasDeclaration) isAliasDeclaration() inout
966
    {
967 1
        return this;
968
    }
969

970
    /** Returns: `true` if this instance was created to make a template parameter
971
    visible in the scope of a template body, `false` otherwise */
972
    extern (D) bool isAliasedTemplateParameter() const
973
    {
974 1
        return !!(storage_class & STC.templateparameter);
975
    }
976

977
    override void accept(Visitor v)
978
    {
979 1
        v.visit(this);
980
    }
981
}
982

983
/***********************************************************
984
 */
985
extern (C++) final class OverDeclaration : Declaration
986
{
987
    Dsymbol overnext;   // next in overload list
988
    Dsymbol aliassym;
989
    bool hasOverloads;
990

991 1
    extern (D) this(Identifier ident, Dsymbol s, bool hasOverloads = true)
992
    {
993 1
        super(ident);
994 1
        this.aliassym = s;
995 1
        this.hasOverloads = hasOverloads;
996 1
        if (hasOverloads)
997
        {
998 1
            if (OverDeclaration od = aliassym.isOverDeclaration())
999 1
                this.hasOverloads = od.hasOverloads;
1000
        }
1001
        else
1002
        {
1003
            // for internal use
1004 0
            assert(!aliassym.isOverDeclaration());
1005
        }
1006
    }
1007

1008
    override const(char)* kind() const
1009
    {
1010 1
        return "overload alias"; // todo
1011
    }
1012

1013
    override bool equals(const RootObject o) const
1014
    {
1015 0
        if (this == o)
1016 0
            return true;
1017

1018 0
        auto s = isDsymbol(o);
1019 0
        if (!s)
1020 0
            return false;
1021

1022 0
        auto od1 = this;
1023 0
        if (auto od2 = s.isOverDeclaration())
1024
        {
1025 0
            return od1.aliassym.equals(od2.aliassym) && od1.hasOverloads == od2.hasOverloads;
1026
        }
1027 0
        if (aliassym == s)
1028
        {
1029 0
            if (hasOverloads)
1030 0
                return true;
1031 0
            if (auto fd = s.isFuncDeclaration())
1032
            {
1033 0
                return fd.isUnique();
1034
            }
1035 0
            if (auto td = s.isTemplateDeclaration())
1036
            {
1037 0
                return td.overnext is null;
1038
            }
1039
        }
1040 0
        return false;
1041
    }
1042

1043
    override bool overloadInsert(Dsymbol s)
1044
    {
1045
        //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1046 1
        if (overnext)
1047 0
            return overnext.overloadInsert(s);
1048 1
        if (s == this)
1049 0
            return true;
1050 1
        overnext = s;
1051 1
        return true;
1052
    }
1053

1054
    override bool isOverloadable() const
1055
    {
1056 1
        return true;
1057
    }
1058

1059
    Dsymbol isUnique()
1060
    {
1061 0
        if (!hasOverloads)
1062
        {
1063 0
            if (aliassym.isFuncDeclaration() ||
1064 0
                aliassym.isTemplateDeclaration())
1065
            {
1066 0
                return aliassym;
1067
            }
1068
        }
1069

1070 0
        Dsymbol result = null;
1071 0
        overloadApply(aliassym, (Dsymbol s)
1072
        {
1073 0
            if (result)
1074
            {
1075 0
                result = null;
1076 0
                return 1; // ambiguous, done
1077
            }
1078
            else
1079
            {
1080 0
                result = s;
1081 0
                return 0;
1082
            }
1083
        });
1084 0
        return result;
1085
    }
1086

1087
    override inout(OverDeclaration) isOverDeclaration() inout
1088
    {
1089 1
        return this;
1090
    }
1091

1092
    override void accept(Visitor v)
1093
    {
1094 1
        v.visit(this);
1095
    }
1096
}
1097

1098
/***********************************************************
1099
 */
1100
extern (C++) class VarDeclaration : Declaration
1101
{
1102
    Initializer _init;
1103
    FuncDeclarations nestedrefs;    // referenced by these lexically nested functions
1104
    Dsymbol aliassym;               // if redone as alias to another symbol
1105
    VarDeclaration lastVar;         // Linked list of variables for goto-skips-init detection
1106
    Expression edtor;               // if !=null, does the destruction of the variable
1107
    IntRange* range;                // if !=null, the variable is known to be within the range
1108
    VarDeclarations* maybes;        // STC.maybescope variables that are assigned to this STC.maybescope variable
1109

1110
    uint endlinnum;                 // line number of end of scope that this var lives in
1111
    uint offset;
1112
    uint sequenceNumber;            // order the variables are declared
1113
    __gshared uint nextSequenceNumber;   // the counter for sequenceNumber
1114
    structalign_t alignment;
1115

1116
    // When interpreting, these point to the value (NULL if value not determinable)
1117
    // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1118
    enum AdrOnStackNone = ~0u;
1119
    uint ctfeAdrOnStack;
1120

1121
    bool isargptr;                  // if parameter that _argptr points to
1122
    bool ctorinit;                  // it has been initialized in a ctor
1123
    bool iscatchvar;                // this is the exception object variable in catch() clause
1124
    bool isowner;                   // this is an Owner, despite it being `scope`
1125

1126
    // Both these mean the var is not rebindable once assigned,
1127
    // and the destructor gets run when it goes out of scope
1128
    bool onstack;                   // it is a class that was allocated on the stack
1129
    bool mynew;                     // it is a class new'd with custom operator new
1130

1131
    byte canassign;                  // it can be assigned to
1132
    bool overlapped;                // if it is a field and has overlapping
1133
    bool overlapUnsafe;             // if it is an overlapping field and the overlaps are unsafe
1134
    bool doNotInferScope;           // do not infer 'scope' for this variable
1135
    bool doNotInferReturn;          // do not infer 'return' for this variable
1136
    ubyte isdataseg;                // private data for isDataseg 0 unset, 1 true, 2 false
1137

1138 1
    final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1139
    in
1140
    {
1141 1
        assert(ident);
1142
    }
1143
    do
1144
    {
1145
        //printf("VarDeclaration('%s')\n", ident.toChars());
1146 1
        super(loc, ident);
1147
        debug
1148
        {
1149 1
            if (!type && !_init)
1150
            {
1151
                //printf("VarDeclaration('%s')\n", ident.toChars());
1152
                //*(char*)0=0;
1153
            }
1154
        }
1155

1156 1
        assert(type || _init);
1157 1
        this.type = type;
1158 1
        this._init = _init;
1159 1
        ctfeAdrOnStack = AdrOnStackNone;
1160 1
        this.storage_class = storage_class;
1161 1
        sequenceNumber = ++nextSequenceNumber;
1162
    }
1163

1164
    static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1165
    {
1166 0
        return new VarDeclaration(loc, type, ident, _init, storage_class);
1167
    }
1168

1169
    override Dsymbol syntaxCopy(Dsymbol s)
1170
    {
1171
        //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1172 1
        assert(!s);
1173 1
        auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1174 1
        v.comment = comment;
1175 1
        return v;
1176
    }
1177

1178
    override final void setFieldOffset(AggregateDeclaration ad, uint* poffset, bool isunion)
1179
    {
1180
        //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1181

1182 1
        if (aliassym)
1183
        {
1184
            // If this variable was really a tuple, set the offsets for the tuple fields
1185 1
            TupleDeclaration v2 = aliassym.isTupleDeclaration();
1186 1
            assert(v2);
1187 1
            for (size_t i = 0; i < v2.objects.dim; i++)
1188
            {
1189 1
                RootObject o = (*v2.objects)[i];
1190 1
                assert(o.dyncast() == DYNCAST.expression);
1191 1
                Expression e = cast(Expression)o;
1192 1
                assert(e.op == TOK.dSymbol);
1193 1
                DsymbolExp se = cast(DsymbolExp)e;
1194 1
                se.s.setFieldOffset(ad, poffset, isunion);
1195
            }
1196 1
            return;
1197
        }
1198

1199 1
        if (!isField())
1200 1
            return;
1201 1
        assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter | STC.tls)));
1202

1203
        //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1204

1205
        /* Fields that are tuples appear both as part of TupleDeclarations and
1206
         * as members. That means ignore them if they are already a field.
1207
         */
1208 1
        if (offset)
1209
        {
1210
            // already a field
1211 1
            *poffset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1212 1
            return;
1213
        }
1214 1
        for (size_t i = 0; i < ad.fields.dim; i++)
1215
        {
1216 1
            if (ad.fields[i] == this)
1217
            {
1218
                // already a field
1219 1
                *poffset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1220 1
                return;
1221
            }
1222
        }
1223

1224
        // Check for forward referenced types which will fail the size() call
1225 1
        Type t = type.toBasetype();
1226 1
        if (storage_class & STC.ref_)
1227
        {
1228
            // References are the size of a pointer
1229 0
            t = Type.tvoidptr;
1230
        }
1231 1
        Type tv = t.baseElemOf();
1232 1
        if (tv.ty == Tstruct)
1233
        {
1234 1
            auto ts = cast(TypeStruct)tv;
1235 1
            assert(ts.sym != ad);   // already checked in ad.determineFields()
1236 1
            if (!ts.sym.determineSize(loc))
1237
            {
1238 1
                type = Type.terror;
1239 1
                errors = true;
1240 1
                return;
1241
            }
1242
        }
1243

1244
        // List in ad.fields. Even if the type is error, it's necessary to avoid
1245
        // pointless error diagnostic "more initializers than fields" on struct literal.
1246 1
        ad.fields.push(this);
1247

1248 1
        if (t.ty == Terror)
1249 1
            return;
1250

1251 1
        const sz = t.size(loc);
1252 1
        assert(sz != SIZE_INVALID && sz < uint.max);
1253 1
        uint memsize = cast(uint)sz;                // size of member
1254 1
        uint memalignsize = target.fieldalign(t);   // size of member for alignment purposes
1255 1
        offset = AggregateDeclaration.placeField(
1256
            poffset,
1257
            memsize, memalignsize, alignment,
1258
            &ad.structsize, &ad.alignsize,
1259
            isunion);
1260

1261
        //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1262
        //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1263
    }
1264

1265
    override const(char)* kind() const
1266
    {
1267 1
        return "variable";
1268
    }
1269

1270
    override final inout(AggregateDeclaration) isThis() inout
1271
    {
1272 1
        if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe)))
1273
        {
1274
            /* The casting is necessary because `s = s.parent` is otherwise rejected
1275
             */
1276 1
            for (auto s = cast(Dsymbol)this; s; s = s.parent)
1277
            {
1278 1
                auto ad = (cast(inout)s).isMember();
1279 1
                if (ad)
1280 1
                    return ad;
1281 1
                if (!s.parent || !s.parent.isTemplateMixin())
1282 1
                    break;
1283
            }
1284
        }
1285 1
        return null;
1286
    }
1287

1288
    override final bool needThis()
1289
    {
1290
        //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1291 1
        return isField();
1292
    }
1293

1294
    override final bool isExport() const
1295
    {
1296 1
        return protection.kind == Prot.Kind.export_;
1297
    }
1298

1299
    override final bool isImportedSymbol() const
1300
    {
1301 1
        if (protection.kind == Prot.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
1302 0
            return true;
1303 1
        return false;
1304
    }
1305

1306
    /*******************************
1307
     * Does symbol go into data segment?
1308
     * Includes extern variables.
1309
     */
1310
    override final bool isDataseg()
1311
    {
1312
        version (none)
1313
        {
1314
            printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1315
            printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1316
                   storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1317
            printf("parent = '%s'\n", parent.toChars());
1318
        }
1319

1320 1
        if (isdataseg == 0) // the value is not cached
1321
        {
1322 1
            isdataseg = 2; // The Variables does not go into the datasegment
1323

1324 1
            if (!canTakeAddressOf())
1325
            {
1326 1
                return false;
1327
            }
1328

1329 1
            Dsymbol parent = toParent();
1330 1
            if (!parent && !(storage_class & STC.static_))
1331
            {
1332 0
                error("forward referenced");
1333 0
                type = Type.terror;
1334
            }
1335 1
            else if (storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared) ||
1336 1
                parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1337
            {
1338 1
                assert(!isParameter() && !isResult());
1339 1
                isdataseg = 1; // It is in the DataSegment
1340
            }
1341
        }
1342

1343 1
        return (isdataseg == 1);
1344
    }
1345
    /************************************
1346
     * Does symbol go into thread local storage?
1347
     */
1348
    override final bool isThreadlocal()
1349
    {
1350
        //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1351
        /* Data defaults to being thread-local. It is not thread-local
1352
         * if it is immutable, const or shared.
1353
         */
1354 1
        bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1355
        //printf("\treturn %d\n", i);
1356 1
        return i;
1357
    }
1358

1359
    /********************************************
1360
     * Can variable be read and written by CTFE?
1361
     */
1362
    final bool isCTFE()
1363
    {
1364 1
        return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1365
    }
1366

1367
    final bool isOverlappedWith(VarDeclaration v)
1368
    {
1369 1
        const vsz = v.type.size();
1370 1
        const tsz = type.size();
1371 1
        assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1372 1
        return    offset < v.offset + vsz &&
1373 1
                v.offset <   offset + tsz;
1374
    }
1375

1376
    override final bool hasPointers()
1377
    {
1378
        //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1379 1
        return (!isDataseg() && type.hasPointers());
1380
    }
1381

1382
    /*************************************
1383
     * Return true if we can take the address of this variable.
1384
     */
1385
    final bool canTakeAddressOf()
1386
    {
1387 1
        return !(storage_class & STC.manifest);
1388
    }
1389

1390
    /******************************************
1391
     * Return true if variable needs to call the destructor.
1392
     */
1393
    final bool needsScopeDtor()
1394
    {
1395
        //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1396 1
        return edtor && !(storage_class & STC.nodtor);
1397
    }
1398

1399
    /******************************************
1400
     * If a variable has a scope destructor call, return call for it.
1401
     * Otherwise, return NULL.
1402
     */
1403
    extern (D) final Expression callScopeDtor(Scope* sc)
1404
    {
1405
        //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1406

1407
        // Destruction of STC.field's is handled by buildDtor()
1408 1
        if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1409
        {
1410 1
            return null;
1411
        }
1412

1413 1
        if (iscatchvar)
1414 1
            return null;    // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1415

1416 1
        Expression e = null;
1417
        // Destructors for structs and arrays of structs
1418 1
        Type tv = type.baseElemOf();
1419 1
        if (tv.ty == Tstruct)
1420
        {
1421 1
            StructDeclaration sd = (cast(TypeStruct)tv).sym;
1422 1
            if (!sd.dtor || sd.errors)
1423 1
                return null;
1424

1425 1
            const sz = type.size();
1426 1
            assert(sz != SIZE_INVALID);
1427 1
            if (!sz)
1428 0
                return null;
1429

1430 1
            if (type.toBasetype().ty == Tstruct)
1431
            {
1432
                // v.__xdtor()
1433 1
                e = new VarExp(loc, this);
1434

1435
                /* This is a hack so we can call destructors on const/immutable objects.
1436
                 * Need to add things like "const ~this()" and "immutable ~this()" to
1437
                 * fix properly.
1438
                 */
1439 1
                e.type = e.type.mutableOf();
1440

1441
                // Enable calling destructors on shared objects.
1442
                // The destructor is always a single, non-overloaded function,
1443
                // and must serve both shared and non-shared objects.
1444 1
                e.type = e.type.unSharedOf;
1445

1446 1
                e = new DotVarExp(loc, e, sd.dtor, false);
1447 1
                e = new CallExp(loc, e);
1448
            }
1449
            else
1450
            {
1451
                // __ArrayDtor(v[0 .. n])
1452 1
                e = new VarExp(loc, this);
1453

1454 1
                const sdsz = sd.type.size();
1455 1
                assert(sdsz != SIZE_INVALID && sdsz != 0);
1456 1
                const n = sz / sdsz;
1457 1
                e = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), new IntegerExp(loc, n, Type.tsize_t));
1458

1459
                // Prevent redundant bounds check
1460 1
                (cast(SliceExp)e).upperIsInBounds = true;
1461 1
                (cast(SliceExp)e).lowerIsLessThanUpper = true;
1462

1463
                // This is a hack so we can call destructors on const/immutable objects.
1464 1
                e.type = sd.type.arrayOf();
1465

1466 1
                e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), e);
1467
            }
1468 1
            return e;
1469
        }
1470
        // Destructors for classes
1471 1
        if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1472
        {
1473 1
            for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1474
            {
1475
                /* We can do better if there's a way with onstack
1476
                 * classes to determine if there's no way the monitor
1477
                 * could be set.
1478
                 */
1479
                //if (cd.isInterfaceDeclaration())
1480
                //    error("interface `%s` cannot be scope", cd.toChars());
1481

1482
                // Destroying C++ scope classes crashes currently. Since C++ class dtors are not currently supported, simply do not run dtors for them.
1483
                // See https://issues.dlang.org/show_bug.cgi?id=13182
1484 1
                if (cd.classKind == ClassKind.cpp)
1485
                {
1486 1
                    break;
1487
                }
1488 1
                if (mynew || onstack) // if any destructors
1489
                {
1490
                    // delete this;
1491 1
                    Expression ec;
1492 1
                    ec = new VarExp(loc, this);
1493 1
                    e = new DeleteExp(loc, ec, true);
1494 1
                    e.type = Type.tvoid;
1495 1
                    break;
1496
                }
1497
            }
1498
        }
1499 1
        return e;
1500
    }
1501

1502
    /*******************************************
1503
     * If variable has a constant expression initializer, get it.
1504
     * Otherwise, return null.
1505
     */
1506
    extern (D) final Expression getConstInitializer(bool needFullType = true)
1507
    {
1508 1
        assert(type && _init);
1509

1510
        // Ungag errors when not speculative
1511 1
        uint oldgag = global.gag;
1512 1
        if (global.gag)
1513
        {
1514 1
            Dsymbol sym = toParent().isAggregateDeclaration();
1515 1
            if (sym && !sym.isSpeculative())
1516 1
                global.gag = 0;
1517
        }
1518

1519 1
        if (_scope)
1520
        {
1521 1
            inuse++;
1522 1
            _init = _init.initializerSemantic(_scope, type, INITinterpret);
1523 1
            _scope = null;
1524 1
            inuse--;
1525
        }
1526

1527 1
        Expression e = _init.initializerToExpression(needFullType ? type : null);
1528 1
        global.gag = oldgag;
1529 1
        return e;
1530
    }
1531

1532
    /*******************************************
1533
     * Helper function for the expansion of manifest constant.
1534
     */
1535
    extern (D) final Expression expandInitializer(Loc loc)
1536
    {
1537 1
        assert((storage_class & STC.manifest) && _init);
1538

1539 1
        auto e = getConstInitializer();
1540 1
        if (!e)
1541
        {
1542 0
            .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1543 0
            return ErrorExp.get();
1544
        }
1545

1546 1
        e = e.copy();
1547 1
        e.loc = loc;    // for better error message
1548 1
        return e;
1549
    }
1550

1551
    override final void checkCtorConstInit()
1552
    {
1553
        version (none)
1554
        {
1555
            /* doesn't work if more than one static ctor */
1556
            if (ctorinit == 0 && isCtorinit() && !isField())
1557
                error("missing initializer in static constructor for const variable");
1558
        }
1559
    }
1560

1561
    /************************************
1562
     * Check to see if this variable is actually in an enclosing function
1563
     * rather than the current one.
1564
     * Update nestedrefs[], closureVars[] and outerVars[].
1565
     * Returns: true if error occurs.
1566
     */
1567
    extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1568
    {
1569
        //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1570 1
        if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1571 1
            return false;
1572 1
        if (!parent || parent == sc.parent)
1573 1
            return false;
1574 1
        if (isDataseg() || (storage_class & STC.manifest))
1575 1
            return false;
1576

1577
        // The current function
1578 1
        FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1579 1
        if (!fdthis)
1580 1
            return false; // out of function scope
1581

1582 1
        Dsymbol p = toParent2();
1583

1584
        // Function literals from fdthis to p must be delegates
1585 1
        ensureStaticLinkTo(fdthis, p);
1586

1587
        // The function that this variable is in
1588 1
        FuncDeclaration fdv = p.isFuncDeclaration();
1589 1
        if (!fdv || fdv == fdthis)
1590 1
            return false;
1591

1592
        // Add fdthis to nestedrefs[] if not already there
1593 1
        if (!nestedrefs.contains(fdthis))
1594 1
            nestedrefs.push(fdthis);
1595

1596
        //printf("\tfdv = %s\n", fdv.toChars());
1597
        //printf("\tfdthis = %s\n", fdthis.toChars());
1598 1
        if (loc.isValid())
1599
        {
1600 1
            if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1601 1
                return true;
1602
        }
1603

1604
        // Add this VarDeclaration to fdv.closureVars[] if not already there
1605 1
        if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1606
            // https://issues.dlang.org/show_bug.cgi?id=17605
1607 1
            (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly))
1608
           )
1609
        {
1610 1
            if (!fdv.closureVars.contains(this))
1611 1
                fdv.closureVars.push(this);
1612
        }
1613

1614 1
        if (!fdthis.outerVars.contains(this))
1615 1
            fdthis.outerVars.push(this);
1616

1617
        //printf("fdthis is %s\n", fdthis.toChars());
1618
        //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1619
        // __dollar creates problems because it isn't a real variable
1620
        // https://issues.dlang.org/show_bug.cgi?id=3326
1621 1
        if (ident == Id.dollar)
1622
        {
1623 0
            .error(loc, "cannnot use `$` inside a function literal");
1624 0
            return true;
1625
        }
1626 1
        if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1627
        {
1628 1
            ExpInitializer ez = _init.isExpInitializer();
1629 1
            assert(ez);
1630 1
            Expression e = ez.exp;
1631 1
            if (e.op == TOK.construct || e.op == TOK.blit)
1632 1
                e = (cast(AssignExp)e).e2;
1633 1
            return lambdaCheckForNestedRef(e, sc);
1634
        }
1635

1636 1
        return false;
1637
    }
1638

1639
    override final Dsymbol toAlias()
1640
    {
1641
        //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1642 1
        if ((!type || !type.deco) && _scope)
1643 1
            dsymbolSemantic(this, _scope);
1644

1645 1
        assert(this != aliassym);
1646 1
        Dsymbol s = aliassym ? aliassym.toAlias() : this;
1647 1
        return s;
1648
    }
1649

1650
    // Eliminate need for dynamic_cast
1651
    override final inout(VarDeclaration) isVarDeclaration() inout
1652
    {
1653 1
        return this;
1654
    }
1655

1656
    override void accept(Visitor v)
1657
    {
1658 1
        v.visit(this);
1659
    }
1660

1661
    /**********************************
1662
     * Determine if `this` has a lifetime that lasts past
1663
     * the destruction of `v`
1664
     * Params:
1665
     *  v = variable to test against
1666
     * Returns:
1667
     *  true if it does
1668
     */
1669
    final bool enclosesLifetimeOf(VarDeclaration v) const pure
1670
    {
1671 1
        return sequenceNumber < v.sequenceNumber;
1672
    }
1673

1674
    /***************************************
1675
     * Add variable to maybes[].
1676
     * When a maybescope variable `v` is assigned to a maybescope variable `this`,
1677
     * we cannot determine if `this` is actually scope until the semantic
1678
     * analysis for the function is completed. Thus, we save the data
1679
     * until then.
1680
     * Params:
1681
     *  v = an STC.maybescope variable that was assigned to `this`
1682
     */
1683
    final void addMaybe(VarDeclaration v)
1684
    {
1685
        //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
1686 1
        if (!maybes)
1687 1
            maybes = new VarDeclarations();
1688 1
        maybes.push(v);
1689
    }
1690
}
1691

1692
/***********************************************************
1693
 * This is a shell around a back end symbol
1694
 */
1695
extern (C++) final class SymbolDeclaration : Declaration
1696
{
1697
    StructDeclaration dsym;
1698

1699 1
    extern (D) this(const ref Loc loc, StructDeclaration dsym)
1700
    {
1701 1
        super(loc, dsym.ident);
1702 1
        this.dsym = dsym;
1703 1
        storage_class |= STC.const_;
1704
    }
1705

1706
    // Eliminate need for dynamic_cast
1707
    override inout(SymbolDeclaration) isSymbolDeclaration() inout
1708
    {
1709 1
        return this;
1710
    }
1711

1712
    override void accept(Visitor v)
1713
    {
1714 1
        v.visit(this);
1715
    }
1716
}
1717

1718
/***********************************************************
1719
 */
1720
extern (C++) class TypeInfoDeclaration : VarDeclaration
1721
{
1722
    Type tinfo;
1723

1724 1
    final extern (D) this(Type tinfo)
1725
    {
1726 1
        super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
1727 1
        this.tinfo = tinfo;
1728 1
        storage_class = STC.static_ | STC.gshared;
1729 1
        protection = Prot(Prot.Kind.public_);
1730 1
        linkage = LINK.c;
1731 1
        alignment = target.ptrsize;
1732
    }
1733

1734
    static TypeInfoDeclaration create(Type tinfo)
1735
    {
1736 1
        return new TypeInfoDeclaration(tinfo);
1737
    }
1738

1739
    override final Dsymbol syntaxCopy(Dsymbol s)
1740
    {
1741 0
        assert(0); // should never be produced by syntax
1742
    }
1743

1744
    override final const(char)* toChars() const
1745
    {
1746
        //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
1747 1
        OutBuffer buf;
1748 1
        buf.writestring("typeid(");
1749 1
        buf.writestring(tinfo.toChars());
1750 1
        buf.writeByte(')');
1751 1
        return buf.extractChars();
1752
    }
1753

1754
    override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout
1755
    {
1756 1
        return this;
1757
    }
1758

1759
    override void accept(Visitor v)
1760
    {
1761 1
        v.visit(this);
1762
    }
1763
}
1764

1765
/***********************************************************
1766
 */
1767
extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
1768
{
1769 1
    extern (D) this(Type tinfo)
1770
    {
1771 1
        super(tinfo);
1772 1
        if (!Type.typeinfostruct)
1773
        {
1774 0
            ObjectNotFound(Id.TypeInfo_Struct);
1775
        }
1776 1
        type = Type.typeinfostruct.type;
1777
    }
1778

1779
    static TypeInfoStructDeclaration create(Type tinfo)
1780
    {
1781 1
        return new TypeInfoStructDeclaration(tinfo);
1782
    }
1783

1784
    override void accept(Visitor v)
1785
    {
1786 1
        v.visit(this);
1787
    }
1788
}
1789

1790
/***********************************************************
1791
 */
1792
extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
1793
{
1794 1
    extern (D) this(Type tinfo)
1795
    {
1796 1
        super(tinfo);
1797 1
        if (!Type.typeinfoclass)
1798
        {
1799 0
            ObjectNotFound(Id.TypeInfo_Class);
1800
        }
1801 1
        type = Type.typeinfoclass.type;
1802
    }
1803

1804
    static TypeInfoClassDeclaration create(Type tinfo)
1805
    {
1806 1
        return new TypeInfoClassDeclaration(tinfo);
1807
    }
1808

1809
    override void accept(Visitor v)
1810
    {
1811 1
        v.visit(this);
1812
    }
1813
}
1814

1815
/***********************************************************
1816
 */
1817
extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
1818
{
1819 1
    extern (D) this(Type tinfo)
1820
    {
1821 1
        super(tinfo);
1822 1
        if (!Type.typeinfointerface)
1823
        {
1824 0
            ObjectNotFound(Id.TypeInfo_Interface);
1825
        }
1826 1
        type = Type.typeinfointerface.type;
1827
    }
1828

1829
    static TypeInfoInterfaceDeclaration create(Type tinfo)
1830
    {
1831 1
        return new TypeInfoInterfaceDeclaration(tinfo);
1832
    }
1833

1834
    override void accept(Visitor v)
1835
    {
1836 1
        v.visit(this);
1837
    }
1838
}
1839

1840
/***********************************************************
1841
 */
1842
extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
1843
{
1844 1
    extern (D) this(Type tinfo)
1845
    {
1846 1
        super(tinfo);
1847 1
        if (!Type.typeinfopointer)
1848
        {
1849 0
            ObjectNotFound(Id.TypeInfo_Pointer);
1850
        }
1851 1
        type = Type.typeinfopointer.type;
1852
    }
1853

1854
    static TypeInfoPointerDeclaration create(Type tinfo)
1855
    {
1856 1
        return new TypeInfoPointerDeclaration(tinfo);
1857
    }
1858

1859
    override void accept(Visitor v)
1860
    {
1861 1
        v.visit(this);
1862
    }
1863
}
1864

1865
/***********************************************************
1866
 */
1867
extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
1868
{
1869 1
    extern (D) this(Type tinfo)
1870
    {
1871 1
        super(tinfo);
1872 1
        if (!Type.typeinfoarray)
1873
        {
1874 0
            ObjectNotFound(Id.TypeInfo_Array);
1875
        }
1876 1
        type = Type.typeinfoarray.type;
1877
    }
1878

1879
    static TypeInfoArrayDeclaration create(Type tinfo)
1880
    {
1881 1
        return new TypeInfoArrayDeclaration(tinfo);
1882
    }
1883

1884
    override void accept(Visitor v)
1885
    {
1886 1
        v.visit(this);
1887
    }
1888
}
1889

1890
/***********************************************************
1891
 */
1892
extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
1893
{
1894 1
    extern (D) this(Type tinfo)
1895
    {
1896 1
        super(tinfo);
1897 1
        if (!Type.typeinfostaticarray)
1898
        {
1899 0
            ObjectNotFound(Id.TypeInfo_StaticArray);
1900
        }
1901 1
        type = Type.typeinfostaticarray.type;
1902
    }
1903

1904
    static TypeInfoStaticArrayDeclaration create(Type tinfo)
1905
    {
1906 1
        return new TypeInfoStaticArrayDeclaration(tinfo);
1907
    }
1908

1909
    override void accept(Visitor v)
1910
    {
1911 1
        v.visit(this);
1912
    }
1913
}
1914

1915
/***********************************************************
1916
 */
1917
extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
1918
{
1919 1
    extern (D) this(Type tinfo)
1920
    {
1921 1
        super(tinfo);
1922 1
        if (!Type.typeinfoassociativearray)
1923
        {
1924 0
            ObjectNotFound(Id.TypeInfo_AssociativeArray);
1925
        }
1926 1
        type = Type.typeinfoassociativearray.type;
1927
    }
1928

1929
    static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
1930
    {
1931 1
        return new TypeInfoAssociativeArrayDeclaration(tinfo);
1932
    }
1933

1934
    override void accept(Visitor v)
1935
    {
1936 1
        v.visit(this);
1937
    }
1938
}
1939

1940
/***********************************************************
1941
 */
1942
extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
1943
{
1944 1
    extern (D) this(Type tinfo)
1945
    {
1946 1
        super(tinfo);
1947 1
        if (!Type.typeinfoenum)
1948
        {
1949 0
            ObjectNotFound(Id.TypeInfo_Enum);
1950
        }
1951 1
        type = Type.typeinfoenum.type;
1952
    }
1953

1954
    static TypeInfoEnumDeclaration create(Type tinfo)
1955
    {
1956 1
        return new TypeInfoEnumDeclaration(tinfo);
1957
    }
1958

1959
    override void accept(Visitor v)
1960
    {
1961 1
        v.visit(this);
1962
    }
1963
}
1964

1965
/***********************************************************
1966
 */
1967
extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
1968
{
1969 1
    extern (D) this(Type tinfo)
1970
    {
1971 1
        super(tinfo);
1972 1
        if (!Type.typeinfofunction)
1973
        {
1974 0
            ObjectNotFound(Id.TypeInfo_Function);
1975
        }
1976 1
        type = Type.typeinfofunction.type;
1977
    }
1978

1979
    static TypeInfoFunctionDeclaration create(Type tinfo)
1980
    {
1981 1
        return new TypeInfoFunctionDeclaration(tinfo);
1982
    }
1983

1984
    override void accept(Visitor v)
1985
    {
1986 1
        v.visit(this);
1987
    }
1988
}
1989

1990
/***********************************************************
1991
 */
1992
extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
1993
{
1994 1
    extern (D) this(Type tinfo)
1995
    {
1996 1
        super(tinfo);
1997 1
        if (!Type.typeinfodelegate)
1998
        {
1999 0
            ObjectNotFound(Id.TypeInfo_Delegate);
2000
        }
2001 1
        type = Type.typeinfodelegate.type;
2002
    }
2003

2004
    static TypeInfoDelegateDeclaration create(Type tinfo)
2005
    {
2006 1
        return new TypeInfoDelegateDeclaration(tinfo);
2007
    }
2008

2009
    override void accept(Visitor v)
2010
    {
2011 1
        v.visit(this);
2012
    }
2013
}
2014

2015
/***********************************************************
2016
 */
2017
extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2018
{
2019 1
    extern (D) this(Type tinfo)
2020
    {
2021 1
        super(tinfo);
2022 1
        if (!Type.typeinfotypelist)
2023
        {
2024 0
            ObjectNotFound(Id.TypeInfo_Tuple);
2025
        }
2026 1
        type = Type.typeinfotypelist.type;
2027
    }
2028

2029
    static TypeInfoTupleDeclaration create(Type tinfo)
2030
    {
2031 1
        return new TypeInfoTupleDeclaration(tinfo);
2032
    }
2033

2034
    override void accept(Visitor v)
2035
    {
2036 1
        v.visit(this);
2037
    }
2038
}
2039

2040
/***********************************************************
2041
 */
2042
extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2043
{
2044 1
    extern (D) this(Type tinfo)
2045
    {
2046 1
        super(tinfo);
2047 1
        if (!Type.typeinfoconst)
2048
        {
2049 0
            ObjectNotFound(Id.TypeInfo_Const);
2050
        }
2051 1
        type = Type.typeinfoconst.type;
2052
    }
2053

2054
    static TypeInfoConstDeclaration create(Type tinfo)
2055
    {
2056 1
        return new TypeInfoConstDeclaration(tinfo);
2057
    }
2058

2059
    override void accept(Visitor v)
2060
    {
2061 1
        v.visit(this);
2062
    }
2063
}
2064

2065
/***********************************************************
2066
 */
2067
extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2068
{
2069 1
    extern (D) this(Type tinfo)
2070
    {
2071 1
        super(tinfo);
2072 1
        if (!Type.typeinfoinvariant)
2073
        {
2074 0
            ObjectNotFound(Id.TypeInfo_Invariant);
2075
        }
2076 1
        type = Type.typeinfoinvariant.type;
2077
    }
2078

2079
    static TypeInfoInvariantDeclaration create(Type tinfo)
2080
    {
2081 1
        return new TypeInfoInvariantDeclaration(tinfo);
2082
    }
2083

2084
    override void accept(Visitor v)
2085
    {
2086 1
        v.visit(this);
2087
    }
2088
}
2089

2090
/***********************************************************
2091
 */
2092
extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2093
{
2094 1
    extern (D) this(Type tinfo)
2095
    {
2096 1
        super(tinfo);
2097 1
        if (!Type.typeinfoshared)
2098
        {
2099 0
            ObjectNotFound(Id.TypeInfo_Shared);
2100
        }
2101 1
        type = Type.typeinfoshared.type;
2102
    }
2103

2104
    static TypeInfoSharedDeclaration create(Type tinfo)
2105
    {
2106 1
        return new TypeInfoSharedDeclaration(tinfo);
2107
    }
2108

2109
    override void accept(Visitor v)
2110
    {
2111 1
        v.visit(this);
2112
    }
2113
}
2114

2115
/***********************************************************
2116
 */
2117
extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2118
{
2119 1
    extern (D) this(Type tinfo)
2120
    {
2121 1
        super(tinfo);
2122 1
        if (!Type.typeinfowild)
2123
        {
2124 0
            ObjectNotFound(Id.TypeInfo_Wild);
2125
        }
2126 1
        type = Type.typeinfowild.type;
2127
    }
2128

2129
    static TypeInfoWildDeclaration create(Type tinfo)
2130
    {
2131 1
        return new TypeInfoWildDeclaration(tinfo);
2132
    }
2133

2134
    override void accept(Visitor v)
2135
    {
2136 1
        v.visit(this);
2137
    }
2138
}
2139

2140
/***********************************************************
2141
 */
2142
extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2143
{
2144 1
    extern (D) this(Type tinfo)
2145
    {
2146 1
        super(tinfo);
2147 1
        if (!Type.typeinfovector)
2148
        {
2149 0
            ObjectNotFound(Id.TypeInfo_Vector);
2150
        }
2151 1
        type = Type.typeinfovector.type;
2152
    }
2153

2154
    static TypeInfoVectorDeclaration create(Type tinfo)
2155
    {
2156 1
        return new TypeInfoVectorDeclaration(tinfo);
2157
    }
2158

2159
    override void accept(Visitor v)
2160
    {
2161 1
        v.visit(this);
2162
    }
2163
}
2164

2165
/***********************************************************
2166
 * For the "this" parameter to member functions
2167
 */
2168
extern (C++) final class ThisDeclaration : VarDeclaration
2169
{
2170 1
    extern (D) this(const ref Loc loc, Type t)
2171
    {
2172 1
        super(loc, t, Id.This, null);
2173 1
        storage_class |= STC.nodtor;
2174
    }
2175

2176
    override Dsymbol syntaxCopy(Dsymbol s)
2177
    {
2178 0
        assert(0); // should never be produced by syntax
2179
    }
2180

2181
    override inout(ThisDeclaration) isThisDeclaration() inout
2182
    {
2183 1
        return this;
2184
    }
2185

2186
    override void accept(Visitor v)
2187
    {
2188 1
        v.visit(this);
2189
    }
2190
}

Read our documentation on viewing source code .

Loading