1
/**
2
 * Does the semantic 1 pass on the AST, which looks at symbol declarations but not initializers
3
 * or function bodies.
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/dsymbolsem.d, _dsymbolsem.d)
9
 * Documentation:  https://dlang.org/phobos/dmd_dsymbolsem.html
10
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dsymbolsem.d
11
 */
12

13
module dmd.dsymbolsem;
14

15
import core.stdc.stdio;
16
import core.stdc.string;
17

18
import dmd.aggregate;
19
import dmd.aliasthis;
20
import dmd.arraytypes;
21
import dmd.astcodegen;
22
import dmd.attrib;
23
import dmd.blockexit;
24
import dmd.clone;
25
import dmd.compiler;
26
import dmd.dcast;
27
import dmd.dclass;
28
import dmd.declaration;
29
import dmd.denum;
30
import dmd.dimport;
31
import dmd.dinterpret;
32
import dmd.dmangle;
33
import dmd.dmodule;
34
import dmd.dscope;
35
import dmd.dstruct;
36
import dmd.dsymbol;
37
import dmd.dtemplate;
38
import dmd.dversion;
39
import dmd.errors;
40
import dmd.escape;
41
import dmd.expression;
42
import dmd.expressionsem;
43
import dmd.func;
44
import dmd.globals;
45
import dmd.id;
46
import dmd.identifier;
47
import dmd.init;
48
import dmd.initsem;
49
import dmd.hdrgen;
50
import dmd.mtype;
51
import dmd.nogc;
52
import dmd.nspace;
53
import dmd.objc;
54
import dmd.opover;
55
import dmd.parse;
56
import dmd.root.filename;
57
import dmd.root.outbuffer;
58
import dmd.root.rmem;
59
import dmd.root.rootobject;
60
import dmd.semantic2;
61
import dmd.semantic3;
62
import dmd.sideeffect;
63
import dmd.statementsem;
64
import dmd.staticassert;
65
import dmd.tokens;
66
import dmd.utf;
67
import dmd.utils;
68
import dmd.statement;
69
import dmd.target;
70
import dmd.templateparamsem;
71
import dmd.typesem;
72
import dmd.visitor;
73

74
enum LOG = false;
75

76
/*****************************************
77
 * Create inclusive postblit for struct by aggregating
78
 * all the postblits in postblits[] with the postblits for
79
 * all the members.
80
 * Note the close similarity with AggregateDeclaration::buildDtor(),
81
 * and the ordering changes (runs forward instead of backwards).
82
 */
83
private FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
84
{
85
    //printf("StructDeclaration::buildPostBlit() %s\n", sd.toChars());
86 1
    if (sd.isUnionDeclaration())
87 1
        return null;
88

89
    // by default, the storage class of the created postblit
90 1
    StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
91 1
    Loc declLoc = sd.postblits.dim ? sd.postblits[0].loc : sd.loc;
92 1
    Loc loc; // internal code should have no loc to prevent coverage
93

94
    // if any of the postblits are disabled, then the generated postblit
95
    // will be disabled
96 1
    for (size_t i = 0; i < sd.postblits.dim; i++)
97
    {
98 1
        stc |= sd.postblits[i].storage_class & STC.disable;
99
    }
100

101 1
    VarDeclaration[] fieldsToDestroy;
102 1
    auto postblitCalls = new Statements();
103
    // iterate through all the struct fields that are not disabled
104 1
    for (size_t i = 0; i < sd.fields.dim && !(stc & STC.disable); i++)
105
    {
106 1
        auto structField = sd.fields[i];
107 1
        if (structField.storage_class & STC.ref_)
108 0
            continue;
109 1
        if (structField.overlapped)
110 1
            continue;
111
        // if it's a struct declaration or an array of structs
112 1
        Type tv = structField.type.baseElemOf();
113 1
        if (tv.ty != Tstruct)
114 1
            continue;
115 1
        auto sdv = (cast(TypeStruct)tv).sym;
116
        // which has a postblit declaration
117 1
        if (!sdv.postblit)
118 1
            continue;
119 1
        assert(!sdv.isUnionDeclaration());
120

121
        // if this field's postblit is not `nothrow`, add a `scope(failure)`
122
        // block to destroy any prior successfully postblitted fields should
123
        // this field's postblit fail
124 1
        if (fieldsToDestroy.length > 0 && !(cast(TypeFunction)sdv.postblit.type).isnothrow)
125
        {
126
             // create a list of destructors that need to be called
127 1
            Expression[] dtorCalls;
128 1
            foreach(sf; fieldsToDestroy)
129
            {
130 1
                Expression ex;
131 1
                tv = sf.type.toBasetype();
132 1
                if (tv.ty == Tstruct)
133
                {
134
                    // this.v.__xdtor()
135

136 1
                    ex = new ThisExp(loc);
137 1
                    ex = new DotVarExp(loc, ex, sf);
138

139
                    // This is a hack so we can call destructors on const/immutable objects.
140 1
                    ex = new AddrExp(loc, ex);
141 1
                    ex = new CastExp(loc, ex, sf.type.mutableOf().pointerTo());
142 1
                    ex = new PtrExp(loc, ex);
143 1
                    if (stc & STC.safe)
144 0
                        stc = (stc & ~STC.safe) | STC.trusted;
145

146 1
                    auto sfv = (cast(TypeStruct)sf.type.baseElemOf()).sym;
147

148 1
                    ex = new DotVarExp(loc, ex, sfv.dtor, false);
149 1
                    ex = new CallExp(loc, ex);
150

151 1
                    dtorCalls ~= ex;
152
                }
153
                else
154
                {
155
                    // _ArrayDtor((cast(S*)this.v.ptr)[0 .. n])
156

157 1
                    const length = tv.numberOfElems(loc);
158

159 1
                    ex = new ThisExp(loc);
160 1
                    ex = new DotVarExp(loc, ex, sf);
161

162
                    // This is a hack so we can call destructors on const/immutable objects.
163 1
                    ex = new DotIdExp(loc, ex, Id.ptr);
164 1
                    ex = new CastExp(loc, ex, sdv.type.pointerTo());
165 1
                    if (stc & STC.safe)
166 0
                        stc = (stc & ~STC.safe) | STC.trusted;
167

168 1
                    auto se = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type.tsize_t),
169
                                                    new IntegerExp(loc, length, Type.tsize_t));
170
                    // Prevent redundant bounds check
171 1
                    se.upperIsInBounds = true;
172 1
                    se.lowerIsLessThanUpper = true;
173

174 1
                    ex = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
175

176 1
                    dtorCalls ~= ex;
177
                }
178
            }
179 1
            fieldsToDestroy = [];
180

181
            // aggregate the destructor calls
182 1
            auto dtors = new Statements();
183 1
            foreach_reverse(dc; dtorCalls)
184
            {
185 1
                dtors.push(new ExpStatement(loc, dc));
186
            }
187

188
            // put destructor calls in a `scope(failure)` block
189 1
            postblitCalls.push(new ScopeGuardStatement(loc, TOK.onScopeFailure, new CompoundStatement(loc, dtors)));
190
        }
191

192
        // perform semantic on the member postblit in order to
193
        // be able to aggregate it later on with the rest of the
194
        // postblits
195 1
        sdv.postblit.functionSemantic();
196

197 1
        stc = mergeFuncAttrs(stc, sdv.postblit);
198 1
        stc = mergeFuncAttrs(stc, sdv.dtor);
199

200
        // if any of the struct member fields has disabled
201
        // its postblit, then `sd` is not copyable, so no
202
        // postblit is generated
203 1
        if (stc & STC.disable)
204
        {
205 1
            postblitCalls.setDim(0);
206 1
            break;
207
        }
208

209 1
        Expression ex;
210 1
        tv = structField.type.toBasetype();
211 1
        if (tv.ty == Tstruct)
212
        {
213
            // this.v.__xpostblit()
214

215 1
            ex = new ThisExp(loc);
216 1
            ex = new DotVarExp(loc, ex, structField);
217

218
            // This is a hack so we can call postblits on const/immutable objects.
219 1
            ex = new AddrExp(loc, ex);
220 1
            ex = new CastExp(loc, ex, structField.type.mutableOf().pointerTo());
221 1
            ex = new PtrExp(loc, ex);
222 1
            if (stc & STC.safe)
223 1
                stc = (stc & ~STC.safe) | STC.trusted;
224

225 1
            ex = new DotVarExp(loc, ex, sdv.postblit, false);
226 1
            ex = new CallExp(loc, ex);
227
        }
228
        else
229
        {
230
            // _ArrayPostblit((cast(S*)this.v.ptr)[0 .. n])
231

232 1
            const length = tv.numberOfElems(loc);
233 1
            if (length == 0)
234 1
                continue;
235

236 1
            ex = new ThisExp(loc);
237 1
            ex = new DotVarExp(loc, ex, structField);
238

239
            // This is a hack so we can call postblits on const/immutable objects.
240 1
            ex = new DotIdExp(loc, ex, Id.ptr);
241 1
            ex = new CastExp(loc, ex, sdv.type.pointerTo());
242 1
            if (stc & STC.safe)
243 0
                stc = (stc & ~STC.safe) | STC.trusted;
244

245 1
            auto se = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type.tsize_t),
246
                                            new IntegerExp(loc, length, Type.tsize_t));
247
            // Prevent redundant bounds check
248 1
            se.upperIsInBounds = true;
249 1
            se.lowerIsLessThanUpper = true;
250 1
            ex = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayPostblit), se);
251
        }
252 1
        postblitCalls.push(new ExpStatement(loc, ex)); // combine in forward order
253

254
        /* https://issues.dlang.org/show_bug.cgi?id=10972
255
         * When subsequent field postblit calls fail,
256
         * this field should be destructed for Exception Safety.
257
         */
258 1
        if (sdv.dtor)
259
        {
260 1
            sdv.dtor.functionSemantic();
261

262
            // keep a list of fields that need to be destroyed in case
263
            // of a future postblit failure
264 1
            fieldsToDestroy ~= structField;
265
        }
266
    }
267

268
    void checkShared()
269
    {
270 1
        if (sd.type.isShared())
271 0
            stc |= STC.shared_;
272
    }
273

274
    // Build our own "postblit" which executes a, but only if needed.
275 1
    if (postblitCalls.dim || (stc & STC.disable))
276
    {
277
        //printf("Building __fieldPostBlit()\n");
278 1
        checkShared();
279 1
        auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__fieldPostblit);
280 1
        dd.generated = true;
281 1
        dd.storage_class |= STC.inference;
282 1
        dd.fbody = (stc & STC.disable) ? null : new CompoundStatement(loc, postblitCalls);
283 1
        sd.postblits.shift(dd);
284 1
        sd.members.push(dd);
285 1
        dd.dsymbolSemantic(sc);
286
    }
287

288
    // create __xpostblit, which is the generated postblit
289 1
    FuncDeclaration xpostblit = null;
290 1
    switch (sd.postblits.dim)
291
    {
292 1
    case 0:
293 1
        break;
294

295 1
    case 1:
296 1
        xpostblit = sd.postblits[0];
297 1
        break;
298

299 1
    default:
300 1
        Expression e = null;
301 1
        stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
302 1
        for (size_t i = 0; i < sd.postblits.dim; i++)
303
        {
304 1
            auto fd = sd.postblits[i];
305 1
            stc = mergeFuncAttrs(stc, fd);
306 1
            if (stc & STC.disable)
307
            {
308 1
                e = null;
309 1
                break;
310
            }
311 1
            Expression ex = new ThisExp(loc);
312 1
            ex = new DotVarExp(loc, ex, fd, false);
313 1
            ex = new CallExp(loc, ex);
314 1
            e = Expression.combine(e, ex);
315
        }
316

317 1
        checkShared();
318 1
        auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__aggrPostblit);
319 1
        dd.generated = true;
320 1
        dd.storage_class |= STC.inference;
321 1
        dd.fbody = new ExpStatement(loc, e);
322 1
        sd.members.push(dd);
323 1
        dd.dsymbolSemantic(sc);
324 1
        xpostblit = dd;
325 1
        break;
326
    }
327

328
    // Add an __xpostblit alias to make the inclusive postblit accessible
329 1
    if (xpostblit)
330
    {
331 1
        auto _alias = new AliasDeclaration(Loc.initial, Id.__xpostblit, xpostblit);
332 1
        _alias.dsymbolSemantic(sc);
333 1
        sd.members.push(_alias);
334 1
        _alias.addMember(sc, sd); // add to symbol table
335
    }
336 1
    return xpostblit;
337
}
338

339
/**
340
 * Generates a copy constructor declaration with the specified storage
341
 * class for the parameter and the function.
342
 *
343
 * Params:
344
 *  sd = the `struct` that contains the copy constructor
345
 *  paramStc = the storage class of the copy constructor parameter
346
 *  funcStc = the storage class for the copy constructor declaration
347
 *
348
 * Returns:
349
 *  The copy constructor declaration for struct `sd`.
350
 */
351
private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const StorageClass paramStc, const StorageClass funcStc)
352
{
353 1
    auto fparams = new Parameters();
354 1
    auto structType = sd.type;
355 1
    fparams.push(new Parameter(paramStc | STC.ref_ | STC.return_ | STC.scope_, structType, Id.p, null, null));
356 1
    ParameterList pList = ParameterList(fparams);
357 1
    auto tf = new TypeFunction(pList, structType, LINK.d, STC.ref_);
358 1
    auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true);
359 1
    ccd.storage_class |= funcStc;
360 1
    ccd.storage_class |= STC.inference;
361 1
    ccd.generated = true;
362 1
    return ccd;
363
}
364

365
/**
366
 * Generates a trivial copy constructor body that simply does memberwise
367
 * initialization:
368
 *
369
 *    this.field1 = rhs.field1;
370
 *    this.field2 = rhs.field2;
371
 *    ...
372
 *
373
 * Params:
374
 *  sd = the `struct` declaration that contains the copy constructor
375
 *
376
 * Returns:
377
 *  A `CompoundStatement` containing the body of the copy constructor.
378
 */
379
private Statement generateCopyCtorBody(StructDeclaration sd)
380
{
381 1
    Loc loc;
382 1
    Expression e;
383 1
    foreach (v; sd.fields)
384
    {
385 1
        auto ec = new AssignExp(loc,
386
            new DotVarExp(loc, new ThisExp(loc), v),
387
            new DotVarExp(loc, new IdentifierExp(loc, Id.p), v));
388 1
        e = Expression.combine(e, ec);
389
        //printf("e.toChars = %s\n", e.toChars());
390
    }
391 1
    Statement s1 = new ExpStatement(loc, e);
392 1
    return new CompoundStatement(loc, s1);
393
}
394

395
/**
396
 * Generates a copy constructor for a specified `struct` sd if
397
 * the following conditions are met:
398
 *
399
 * 1. sd does not define a copy constructor
400
 * 2. at least one field of sd defines a copy constructor
401
 *
402
 * If the above conditions are met, the following copy constructor
403
 * is generated:
404
 *
405
 * this(ref return scope inout(S) rhs) inout
406
 * {
407
 *    this.field1 = rhs.field1;
408
 *    this.field2 = rhs.field2;
409
 *    ...
410
 * }
411
 *
412
 * Params:
413
 *  sd = the `struct` for which the copy constructor is generated
414
 *  sc = the scope where the copy constructor is generated
415
 *
416
 * Returns:
417
 *  `true` if `struct` sd defines a copy constructor (explicitly or generated),
418
 *  `false` otherwise.
419
 */
420
private bool buildCopyCtor(StructDeclaration sd, Scope* sc)
421
{
422 1
    if (global.errors)
423 1
        return false;
424

425 1
    bool hasPostblit;
426 1
    if (sd.postblit && !sd.postblit.isDisabled())
427 1
        hasPostblit = true;
428

429 1
    auto ctor = sd.search(sd.loc, Id.ctor);
430 1
    CtorDeclaration cpCtor;
431 1
    CtorDeclaration rvalueCtor;
432 1
    if (ctor)
433
    {
434 1
        if (ctor.isOverloadSet())
435 1
            return false;
436 1
        if (auto td = ctor.isTemplateDeclaration())
437 1
            ctor = td.funcroot;
438
    }
439

440 1
    if (!ctor)
441 1
        goto LcheckFields;
442

443 1
    overloadApply(ctor, (Dsymbol s)
444
    {
445 1
        if (s.isTemplateDeclaration())
446 1
            return 0;
447 1
        auto ctorDecl = s.isCtorDeclaration();
448 1
        assert(ctorDecl);
449 1
        if (ctorDecl.isCpCtor)
450
        {
451 1
            if (!cpCtor)
452 1
                cpCtor = ctorDecl;
453 1
            return 0;
454
        }
455

456 1
        auto tf = ctorDecl.type.toTypeFunction();
457 1
        const dim = tf.parameterList.length;
458 1
        if (dim == 1)
459
        {
460 1
            auto param = tf.parameterList[0];
461 1
            if (param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
462
            {
463 1
                rvalueCtor = ctorDecl;
464
            }
465
        }
466 1
        return 0;
467
    });
468

469 1
    if (cpCtor && rvalueCtor)
470
    {
471 1
        .error(sd.loc, "`struct %s` may not define both a rvalue constructor and a copy constructor", sd.toChars());
472 1
        errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here");
473 1
        errorSupplemental(cpCtor.loc, "copy constructor defined here");
474 1
        return true;
475
    }
476 1
    else if (cpCtor)
477
    {
478 1
        return !hasPostblit;
479
    }
480

481
LcheckFields:
482 1
    VarDeclaration fieldWithCpCtor;
483
    // see if any struct members define a copy constructor
484 1
    foreach (v; sd.fields)
485
    {
486 1
        if (v.storage_class & STC.ref_)
487 0
            continue;
488 1
        if (v.overlapped)
489 1
            continue;
490

491 1
        auto ts = v.type.baseElemOf().isTypeStruct();
492 1
        if (!ts)
493 1
            continue;
494 1
        if (ts.sym.hasCopyCtor)
495
        {
496 1
            fieldWithCpCtor = v;
497 1
            break;
498
        }
499
    }
500

501 1
    if (fieldWithCpCtor && rvalueCtor)
502
    {
503 1
        .error(sd.loc, "`struct %s` may not define a rvalue constructor and have fields with copy constructors", sd.toChars());
504 1
        errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here");
505 1
        errorSupplemental(fieldWithCpCtor.loc, "field with copy constructor defined here");
506 1
        return false;
507
    }
508 1
    else if (!fieldWithCpCtor)
509 1
        return false;
510

511 1
    if (hasPostblit)
512 0
        return false;
513

514
    //printf("generating copy constructor for %s\n", sd.toChars());
515 1
    const MOD paramMod = MODFlags.wild;
516 1
    const MOD funcMod = MODFlags.wild;
517 1
    auto ccd = generateCopyCtorDeclaration(sd, ModToStc(paramMod), ModToStc(funcMod));
518 1
    auto copyCtorBody = generateCopyCtorBody(sd);
519 1
    ccd.fbody = copyCtorBody;
520 1
    sd.members.push(ccd);
521 1
    ccd.addMember(sc, sd);
522 1
    const errors = global.startGagging();
523 1
    Scope* sc2 = sc.push();
524 1
    sc2.stc = 0;
525 1
    sc2.linkage = LINK.d;
526 1
    ccd.dsymbolSemantic(sc2);
527 1
    ccd.semantic2(sc2);
528 1
    ccd.semantic3(sc2);
529
    //printf("ccd semantic: %s\n", ccd.type.toChars());
530 1
    sc2.pop();
531 1
    if (global.endGagging(errors))
532
    {
533 1
        ccd.storage_class |= STC.disable;
534 1
        ccd.fbody = null;
535
    }
536 1
    return true;
537
}
538

539
private uint setMangleOverride(Dsymbol s, const(char)[] sym)
540
{
541 1
    if (s.isFuncDeclaration() || s.isVarDeclaration())
542
    {
543 1
        s.isDeclaration().mangleOverride = sym;
544 1
        return 1;
545
    }
546

547 1
    if (auto ad = s.isAttribDeclaration())
548
    {
549 1
        uint nestedCount = 0;
550

551 1
        ad.include(null).foreachDsymbol( (s) { nestedCount += setMangleOverride(s, sym); } );
552

553 1
        return nestedCount;
554
    }
555 0
    return 0;
556
}
557

558
/*************************************
559
 * Does semantic analysis on the public face of declarations.
560
 */
561
extern(C++) void dsymbolSemantic(Dsymbol dsym, Scope* sc)
562
{
563 1
    scope v = new DsymbolSemanticVisitor(sc);
564 1
    dsym.accept(v);
565
}
566

567
structalign_t getAlignment(AlignDeclaration ad, Scope* sc)
568
{
569 1
    if (ad.salign != ad.UNKNOWN)
570 1
        return ad.salign;
571

572 1
    if (!ad.ealign)
573 1
        return ad.salign = STRUCTALIGN_DEFAULT;
574

575 1
    sc = sc.startCTFE();
576 1
    ad.ealign = ad.ealign.expressionSemantic(sc);
577 1
    ad.ealign = resolveProperties(sc, ad.ealign);
578 1
    sc = sc.endCTFE();
579 1
    ad.ealign = ad.ealign.ctfeInterpret();
580

581 1
    if (ad.ealign.op == TOK.error)
582 1
        return ad.salign = STRUCTALIGN_DEFAULT;
583

584 1
    Type tb = ad.ealign.type.toBasetype();
585 1
    auto n = ad.ealign.toInteger();
586

587 1
    if (n < 1 || n & (n - 1) || structalign_t.max < n || !tb.isintegral())
588
    {
589 1
        error(ad.loc, "alignment must be an integer positive power of 2, not %s", ad.ealign.toChars());
590 1
        return ad.salign = STRUCTALIGN_DEFAULT;
591
    }
592

593 1
    return ad.salign = cast(structalign_t)n;
594
}
595

596
const(char)* getMessage(DeprecatedDeclaration dd)
597
{
598 1
    if (auto sc = dd._scope)
599
    {
600 1
        dd._scope = null;
601

602 1
        sc = sc.startCTFE();
603 1
        dd.msg = dd.msg.expressionSemantic(sc);
604 1
        dd.msg = resolveProperties(sc, dd.msg);
605 1
        sc = sc.endCTFE();
606 1
        dd.msg = dd.msg.ctfeInterpret();
607

608 1
        if (auto se = dd.msg.toStringExp())
609 1
            dd.msgstr = se.toStringz().ptr;
610
        else
611 0
            dd.msg.error("compile time constant expected, not `%s`", dd.msg.toChars());
612
    }
613 1
    return dd.msgstr;
614
}
615

616

617
// Returns true if a contract can appear without a function body.
618
package bool allowsContractWithoutBody(FuncDeclaration funcdecl)
619
{
620 1
    assert(!funcdecl.fbody);
621

622
    /* Contracts can only appear without a body when they are virtual
623
     * interface functions or abstract.
624
     */
625 1
    Dsymbol parent = funcdecl.toParent();
626 1
    InterfaceDeclaration id = parent.isInterfaceDeclaration();
627

628 1
    if (!funcdecl.isAbstract() &&
629 1
        (funcdecl.fensures || funcdecl.frequires) &&
630 1
        !(id && funcdecl.isVirtual()))
631
    {
632 1
        auto cd = parent.isClassDeclaration();
633 1
        if (!(cd && cd.isAbstract()))
634 1
            return false;
635
    }
636 1
    return true;
637
}
638

639
private extern(C++) final class DsymbolSemanticVisitor : Visitor
640
{
641
    alias visit = Visitor.visit;
642

643
    Scope* sc;
644 1
    this(Scope* sc)
645
    {
646 1
        this.sc = sc;
647
    }
648

649
    // Save the scope and defer semantic analysis on the Dsymbol.
650
    private void deferDsymbolSemantic(Dsymbol s, Scope *scx)
651
    {
652 1
        s._scope = scx ? scx : sc.copy();
653 1
        s._scope.setNoFree();
654 1
        Module.addDeferredSemantic(s);
655
    }
656

657
    override void visit(Dsymbol dsym)
658
    {
659 0
        dsym.error("%p has no semantic routine", dsym);
660
    }
661

662
    override void visit(ScopeDsymbol) { }
663
    override void visit(Declaration) { }
664

665
    override void visit(AliasThis dsym)
666
    {
667 1
        if (dsym.semanticRun != PASS.init)
668 1
            return;
669

670 1
        if (dsym._scope)
671
        {
672 1
            sc = dsym._scope;
673 1
            dsym._scope = null;
674
        }
675

676 1
        if (!sc)
677 0
            return;
678

679 1
        dsym.semanticRun = PASS.semantic;
680 1
        dsym.isDeprecated_ = !!(sc.stc & STC.deprecated_);
681

682 1
        Dsymbol p = sc.parent.pastMixin();
683 1
        AggregateDeclaration ad = p.isAggregateDeclaration();
684 1
        if (!ad)
685
        {
686 1
            error(dsym.loc, "alias this can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
687 1
            return;
688
        }
689

690 1
        assert(ad.members);
691 1
        Dsymbol s = ad.search(dsym.loc, dsym.ident);
692 1
        if (!s)
693
        {
694 1
            s = sc.search(dsym.loc, dsym.ident, null);
695 1
            if (s)
696 0
                error(dsym.loc, "`%s` is not a member of `%s`", s.toChars(), ad.toChars());
697
            else
698 1
                error(dsym.loc, "undefined identifier `%s`", dsym.ident.toChars());
699 1
            return;
700
        }
701 1
        if (ad.aliasthis && s != ad.aliasthis)
702
        {
703 0
            error(dsym.loc, "there can be only one alias this");
704 0
            return;
705
        }
706

707
        /* disable the alias this conversion so the implicit conversion check
708
         * doesn't use it.
709
         */
710 1
        ad.aliasthis = null;
711

712 1
        Dsymbol sx = s;
713 1
        if (sx.isAliasDeclaration())
714 1
            sx = sx.toAlias();
715 1
        Declaration d = sx.isDeclaration();
716 1
        if (d && !d.isTupleDeclaration())
717
        {
718
            /* https://issues.dlang.org/show_bug.cgi?id=18429
719
             *
720
             * If the identifier in the AliasThis declaration
721
             * is defined later and is a voldemort type, we must
722
             * perform semantic on the declaration to deduce the type.
723
             */
724 1
            if (!d.type)
725 1
                d.dsymbolSemantic(sc);
726

727 1
            Type t = d.type;
728 1
            assert(t);
729 1
            if (ad.type.implicitConvTo(t) > MATCH.nomatch)
730
            {
731 1
                error(dsym.loc, "alias this is not reachable as `%s` already converts to `%s`", ad.toChars(), t.toChars());
732
            }
733
        }
734

735 1
        dsym.sym = s;
736
        // Restore alias this
737 1
        ad.aliasthis = dsym;
738 1
        dsym.semanticRun = PASS.semanticdone;
739
    }
740

741
    override void visit(AliasDeclaration dsym)
742
    {
743 1
        if (dsym.semanticRun >= PASS.semanticdone)
744 1
            return;
745 1
        assert(dsym.semanticRun <= PASS.semantic);
746

747 1
        dsym.storage_class |= sc.stc & STC.deprecated_;
748 1
        dsym.protection = sc.protection;
749 1
        dsym.userAttribDecl = sc.userAttribDecl;
750

751 1
        if (!sc.func && dsym.inNonRoot())
752 1
            return;
753

754 1
        aliasSemantic(dsym, sc);
755
    }
756

757
    override void visit(VarDeclaration dsym)
758
    {
759
        version (none)
760
        {
761
            printf("VarDeclaration::semantic('%s', parent = '%s') sem = %d\n",
762
                   dsym.toChars(), sc.parent ? sc.parent.toChars() : null, dsym.semanticRun);
763
            printf(" type = %s\n", dsym.type ? dsym.type.toChars() : "null");
764
            printf(" stc = x%x\n", dsym.storage_class.stc);
765
            printf(" storage_class = x%llx\n", dsym.storage_class);
766
            printf("linkage = %d\n", dsym.linkage);
767
            //if (strcmp(toChars(), "mul") == 0) assert(0);
768
        }
769
        //if (semanticRun > PASS.init)
770
        //    return;
771
        //semanticRun = PSSsemantic;
772

773 1
        if (dsym.semanticRun >= PASS.semanticdone)
774 1
            return;
775

776 1
        if (sc && sc.inunion && sc.inunion.isAnonDeclaration())
777 1
            dsym.overlapped = true;
778

779 1
        Scope* scx = null;
780 1
        if (dsym._scope)
781
        {
782 1
            sc = dsym._scope;
783 1
            scx = sc;
784 1
            dsym._scope = null;
785
        }
786

787 1
        if (!sc)
788 1
            return;
789

790 1
        dsym.semanticRun = PASS.semantic;
791

792
        /* Pick up storage classes from context, but except synchronized,
793
         * override, abstract, and final.
794
         */
795 1
        dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
796 1
        if (dsym.storage_class & STC.extern_ && dsym._init)
797 0
            dsym.error("extern symbols cannot have initializers");
798

799 1
        dsym.userAttribDecl = sc.userAttribDecl;
800 1
        dsym.cppnamespace = sc.namespace;
801

802 1
        AggregateDeclaration ad = dsym.isThis();
803 1
        if (ad)
804 1
            dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
805

806
        /* If auto type inference, do the inference
807
         */
808 1
        int inferred = 0;
809 1
        if (!dsym.type)
810
        {
811 1
            dsym.inuse++;
812

813
            // Infering the type requires running semantic,
814
            // so mark the scope as ctfe if required
815 1
            bool needctfe = (dsym.storage_class & (STC.manifest | STC.static_)) != 0;
816 1
            if (needctfe)
817
            {
818 1
                sc.flags |= SCOPE.condition;
819 1
                sc = sc.startCTFE();
820
            }
821
            //printf("inferring type for %s with init %s\n", dsym.toChars(), dsym._init.toChars());
822 1
            dsym._init = dsym._init.inferType(sc);
823 1
            dsym.type = dsym._init.initializerToExpression().type;
824 1
            if (needctfe)
825 1
                sc = sc.endCTFE();
826

827 1
            dsym.inuse--;
828 1
            inferred = 1;
829

830
            /* This is a kludge to support the existing syntax for RAII
831
             * declarations.
832
             */
833 1
            dsym.storage_class &= ~STC.auto_;
834 1
            dsym.originalType = dsym.type.syntaxCopy();
835
        }
836
        else
837
        {
838 1
            if (!dsym.originalType)
839 1
                dsym.originalType = dsym.type.syntaxCopy();
840

841
            /* Prefix function attributes of variable declaration can affect
842
             * its type:
843
             *      pure nothrow void function() fp;
844
             *      static assert(is(typeof(fp) == void function() pure nothrow));
845
             */
846 1
            Scope* sc2 = sc.push();
847 1
            sc2.stc |= (dsym.storage_class & STC.FUNCATTR);
848 1
            dsym.inuse++;
849 1
            dsym.type = dsym.type.typeSemantic(dsym.loc, sc2);
850 1
            dsym.inuse--;
851 1
            sc2.pop();
852
        }
853
        //printf(" semantic type = %s\n", dsym.type ? dsym.type.toChars() : "null");
854 1
        if (dsym.type.ty == Terror)
855 1
            dsym.errors = true;
856

857 1
        dsym.type.checkDeprecated(dsym.loc, sc);
858 1
        dsym.linkage = sc.linkage;
859 1
        dsym.parent = sc.parent;
860
        //printf("this = %p, parent = %p, '%s'\n", dsym, dsym.parent, dsym.parent.toChars());
861 1
        dsym.protection = sc.protection;
862

863
        /* If scope's alignment is the default, use the type's alignment,
864
         * otherwise the scope overrrides.
865
         */
866 1
        dsym.alignment = sc.alignment();
867 1
        if (dsym.alignment == STRUCTALIGN_DEFAULT)
868 1
            dsym.alignment = dsym.type.alignment(); // use type's alignment
869

870
        //printf("sc.stc = %x\n", sc.stc);
871
        //printf("storage_class = x%x\n", storage_class);
872

873 1
        if (global.params.vcomplex)
874 1
            dsym.type.checkComplexTransition(dsym.loc, sc);
875

876
        // Calculate type size + safety checks
877 1
        if (sc.func && !sc.intypeof)
878
        {
879 1
            if (dsym.storage_class & STC.gshared && !dsym.isMember())
880
            {
881 1
                if (sc.func.setUnsafe())
882 0
                    dsym.error("__gshared not allowed in safe functions; use shared");
883
            }
884
        }
885

886 1
        Dsymbol parent = dsym.toParent();
887

888 1
        Type tb = dsym.type.toBasetype();
889 1
        Type tbn = tb.baseElemOf();
890 1
        if (tb.ty == Tvoid && !(dsym.storage_class & STC.lazy_))
891
        {
892 1
            if (inferred)
893
            {
894 1
                dsym.error("type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`", dsym.type.toChars(), dsym._init.toChars());
895
            }
896
            else
897 1
                dsym.error("variables cannot be of type `void`");
898 1
            dsym.type = Type.terror;
899 1
            tb = dsym.type;
900
        }
901 1
        if (tb.ty == Tfunction)
902
        {
903 1
            dsym.error("cannot be declared to be a function");
904 1
            dsym.type = Type.terror;
905 1
            tb = dsym.type;
906
        }
907 1
        if (auto ts = tb.isTypeStruct())
908
        {
909 1
            if (!ts.sym.members)
910
            {
911 1
                dsym.error("no definition of struct `%s`", ts.toChars());
912
            }
913
        }
914 1
        if ((dsym.storage_class & STC.auto_) && !inferred)
915 1
            dsym.error("storage class `auto` has no effect if type is not inferred, did you mean `scope`?");
916

917 1
        if (auto tt = tb.isTypeTuple())
918
        {
919
            /* Instead, declare variables for each of the tuple elements
920
             * and add those.
921
             */
922 1
            size_t nelems = Parameter.dim(tt.arguments);
923 1
            Expression ie = (dsym._init && !dsym._init.isVoidInitializer()) ? dsym._init.initializerToExpression() : null;
924 1
            if (ie)
925 1
                ie = ie.expressionSemantic(sc);
926 1
            if (nelems > 0 && ie)
927
            {
928 1
                auto iexps = new Expressions();
929 1
                iexps.push(ie);
930 1
                auto exps = new Expressions();
931 1
                for (size_t pos = 0; pos < iexps.dim; pos++)
932
                {
933
                Lexpand1:
934 1
                    Expression e = (*iexps)[pos];
935 1
                    Parameter arg = Parameter.getNth(tt.arguments, pos);
936 1
                    arg.type = arg.type.typeSemantic(dsym.loc, sc);
937
                    //printf("[%d] iexps.dim = %d, ", pos, iexps.dim);
938
                    //printf("e = (%s %s, %s), ", Token::tochars[e.op], e.toChars(), e.type.toChars());
939
                    //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
940

941 1
                    if (e != ie)
942
                    {
943 1
                        if (iexps.dim > nelems)
944 0
                            goto Lnomatch;
945 1
                        if (e.type.implicitConvTo(arg.type))
946 1
                            continue;
947
                    }
948

949 1
                    if (e.op == TOK.tuple)
950
                    {
951 1
                        TupleExp te = cast(TupleExp)e;
952 1
                        if (iexps.dim - 1 + te.exps.dim > nelems)
953 0
                            goto Lnomatch;
954

955 1
                        iexps.remove(pos);
956 1
                        iexps.insert(pos, te.exps);
957 1
                        (*iexps)[pos] = Expression.combine(te.e0, (*iexps)[pos]);
958 1
                        goto Lexpand1;
959
                    }
960 1
                    else if (isAliasThisTuple(e))
961
                    {
962 1
                        auto v = copyToTemp(0, "__tup", e);
963 1
                        v.dsymbolSemantic(sc);
964 1
                        auto ve = new VarExp(dsym.loc, v);
965 1
                        ve.type = e.type;
966

967 1
                        exps.setDim(1);
968 1
                        (*exps)[0] = ve;
969 1
                        expandAliasThisTuples(exps, 0);
970

971 1
                        for (size_t u = 0; u < exps.dim; u++)
972
                        {
973
                        Lexpand2:
974 1
                            Expression ee = (*exps)[u];
975 1
                            arg = Parameter.getNth(tt.arguments, pos + u);
976 1
                            arg.type = arg.type.typeSemantic(dsym.loc, sc);
977
                            //printf("[%d+%d] exps.dim = %d, ", pos, u, exps.dim);
978
                            //printf("ee = (%s %s, %s), ", Token::tochars[ee.op], ee.toChars(), ee.type.toChars());
979
                            //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
980

981 1
                            size_t iexps_dim = iexps.dim - 1 + exps.dim;
982 1
                            if (iexps_dim > nelems)
983 0
                                goto Lnomatch;
984 1
                            if (ee.type.implicitConvTo(arg.type))
985 1
                                continue;
986

987 1
                            if (expandAliasThisTuples(exps, u) != -1)
988 1
                                goto Lexpand2;
989
                        }
990

991 1
                        if ((*exps)[0] != ve)
992
                        {
993 1
                            Expression e0 = (*exps)[0];
994 1
                            (*exps)[0] = new CommaExp(dsym.loc, new DeclarationExp(dsym.loc, v), e0);
995 1
                            (*exps)[0].type = e0.type;
996

997 1
                            iexps.remove(pos);
998 1
                            iexps.insert(pos, exps);
999 1
                            goto Lexpand1;
1000
                        }
1001
                    }
1002
                }
1003 1
                if (iexps.dim < nelems)
1004 1
                    goto Lnomatch;
1005

1006 1
                ie = new TupleExp(dsym._init.loc, iexps);
1007
            }
1008
        Lnomatch:
1009

1010 1
            if (ie && ie.op == TOK.tuple)
1011
            {
1012 1
                TupleExp te = cast(TupleExp)ie;
1013 1
                size_t tedim = te.exps.dim;
1014 1
                if (tedim != nelems)
1015
                {
1016 0
                    error(dsym.loc, "tuple of %d elements cannot be assigned to tuple of %d elements", cast(int)tedim, cast(int)nelems);
1017 0
                    for (size_t u = tedim; u < nelems; u++) // fill dummy expression
1018 0
                        te.exps.push(ErrorExp.get());
1019
                }
1020
            }
1021

1022 1
            auto exps = new Objects(nelems);
1023 1
            for (size_t i = 0; i < nelems; i++)
1024
            {
1025 1
                Parameter arg = Parameter.getNth(tt.arguments, i);
1026

1027 1
                OutBuffer buf;
1028 1
                buf.printf("__%s_field_%llu", dsym.ident.toChars(), cast(ulong)i);
1029 1
                auto id = Identifier.idPool(buf[]);
1030

1031 1
                Initializer ti;
1032 1
                if (ie)
1033
                {
1034 1
                    Expression einit = ie;
1035 1
                    if (ie.op == TOK.tuple)
1036
                    {
1037 1
                        TupleExp te = cast(TupleExp)ie;
1038 1
                        einit = (*te.exps)[i];
1039 1
                        if (i == 0)
1040 1
                            einit = Expression.combine(te.e0, einit);
1041
                    }
1042 1
                    ti = new ExpInitializer(einit.loc, einit);
1043
                }
1044
                else
1045 1
                    ti = dsym._init ? dsym._init.syntaxCopy() : null;
1046

1047 1
                StorageClass storage_class = STC.temp | dsym.storage_class;
1048 1
                if ((dsym.storage_class & STC.parameter) && (arg.storageClass & STC.parameter))
1049 1
                    storage_class |= arg.storageClass;
1050 1
                auto v = new VarDeclaration(dsym.loc, arg.type, id, ti, storage_class);
1051
                //printf("declaring field %s of type %s\n", v.toChars(), v.type.toChars());
1052 1
                v.dsymbolSemantic(sc);
1053

1054 1
                if (sc.scopesym)
1055
                {
1056
                    //printf("adding %s to %s\n", v.toChars(), sc.scopesym.toChars());
1057 1
                    if (sc.scopesym.members)
1058
                        // Note this prevents using foreach() over members, because the limits can change
1059 1
                        sc.scopesym.members.push(v);
1060
                }
1061

1062 1
                Expression e = new DsymbolExp(dsym.loc, v);
1063 1
                (*exps)[i] = e;
1064
            }
1065 1
            auto v2 = new TupleDeclaration(dsym.loc, dsym.ident, exps);
1066 1
            v2.parent = dsym.parent;
1067 1
            v2.isexp = true;
1068 1
            dsym.aliassym = v2;
1069 1
            dsym.semanticRun = PASS.semanticdone;
1070 1
            return;
1071
        }
1072

1073
        /* Storage class can modify the type
1074
         */
1075 1
        dsym.type = dsym.type.addStorageClass(dsym.storage_class);
1076

1077
        /* Adjust storage class to reflect type
1078
         */
1079 1
        if (dsym.type.isConst())
1080
        {
1081 1
            dsym.storage_class |= STC.const_;
1082 1
            if (dsym.type.isShared())
1083 1
                dsym.storage_class |= STC.shared_;
1084
        }
1085 1
        else if (dsym.type.isImmutable())
1086 1
            dsym.storage_class |= STC.immutable_;
1087 1
        else if (dsym.type.isShared())
1088 1
            dsym.storage_class |= STC.shared_;
1089 1
        else if (dsym.type.isWild())
1090 1
            dsym.storage_class |= STC.wild;
1091

1092 1
        if (StorageClass stc = dsym.storage_class & (STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_))
1093
        {
1094 1
            if (stc == STC.final_)
1095 1
                dsym.error("cannot be `final`, perhaps you meant `const`?");
1096
            else
1097
            {
1098 1
                OutBuffer buf;
1099 1
                stcToBuffer(&buf, stc);
1100 1
                dsym.error("cannot be `%s`", buf.peekChars());
1101
            }
1102 1
            dsym.storage_class &= ~stc; // strip off
1103
        }
1104

1105
        // At this point we can add `scope` to the STC instead of `in`,
1106
        // because we are never going to use this variable's STC for user messages
1107 1
        if (dsym.storage_class & STC.in_ && global.params.previewIn)
1108 1
            dsym.storage_class |= STC.scope_;
1109

1110 1
        if (dsym.storage_class & STC.scope_)
1111
        {
1112 1
            StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.tls | STC.gshared);
1113 1
            if (stc)
1114
            {
1115 1
                OutBuffer buf;
1116 1
                stcToBuffer(&buf, stc);
1117 1
                dsym.error("cannot be `scope` and `%s`", buf.peekChars());
1118
            }
1119 1
            else if (dsym.isMember())
1120
            {
1121 1
                dsym.error("field cannot be `scope`");
1122
            }
1123 1
            else if (!dsym.type.hasPointers())
1124
            {
1125 1
                dsym.storage_class &= ~STC.scope_;     // silently ignore; may occur in generic code
1126
            }
1127
        }
1128

1129 1
        if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe))
1130
        {
1131
        }
1132
        else
1133
        {
1134 1
            AggregateDeclaration aad = parent.isAggregateDeclaration();
1135 1
            if (aad)
1136
            {
1137 1
                if (global.params.vfield && dsym.storage_class & (STC.const_ | STC.immutable_) && dsym._init && !dsym._init.isVoidInitializer())
1138
                {
1139 1
                    const(char)* s = (dsym.storage_class & STC.immutable_) ? "immutable" : "const";
1140 1
                    message(dsym.loc, "`%s.%s` is `%s` field", ad.toPrettyChars(), dsym.toChars(), s);
1141
                }
1142 1
                dsym.storage_class |= STC.field;
1143 1
                if (auto ts = tbn.isTypeStruct())
1144 1
                    if (ts.sym.noDefaultCtor)
1145
                    {
1146 1
                        if (!dsym.isThisDeclaration() && !dsym._init)
1147 1
                            aad.noDefaultCtor = true;
1148
                    }
1149
            }
1150

1151 1
            InterfaceDeclaration id = parent.isInterfaceDeclaration();
1152 1
            if (id)
1153
            {
1154 1
                dsym.error("field not allowed in interface");
1155
            }
1156 1
            else if (aad && aad.sizeok == Sizeok.done)
1157
            {
1158 1
                dsym.error("cannot be further field because it will change the determined %s size", aad.toChars());
1159
            }
1160

1161
            /* Templates cannot add fields to aggregates
1162
             */
1163 1
            TemplateInstance ti = parent.isTemplateInstance();
1164 1
            if (ti)
1165
            {
1166
                // Take care of nested templates
1167 1
                while (1)
1168
                {
1169 1
                    TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
1170 1
                    if (!ti2)
1171 1
                        break;
1172 1
                    ti = ti2;
1173
                }
1174
                // If it's a member template
1175 1
                AggregateDeclaration ad2 = ti.tempdecl.isMember();
1176 1
                if (ad2 && dsym.storage_class != STC.undefined_)
1177
                {
1178 1
                    dsym.error("cannot use template to add field to aggregate `%s`", ad2.toChars());
1179
                }
1180
            }
1181
        }
1182

1183 1
        if ((dsym.storage_class & (STC.ref_ | STC.parameter | STC.foreach_ | STC.temp | STC.result)) == STC.ref_ && dsym.ident != Id.This)
1184
        {
1185 1
            dsym.error("only parameters or `foreach` declarations can be `ref`");
1186
        }
1187

1188 1
        if (dsym.type.hasWild())
1189
        {
1190 1
            if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
1191
            {
1192 1
                dsym.error("only parameters or stack based variables can be `inout`");
1193
            }
1194 1
            FuncDeclaration func = sc.func;
1195 1
            if (func)
1196
            {
1197 1
                if (func.fes)
1198 1
                    func = func.fes.func;
1199 1
                bool isWild = false;
1200 1
                for (FuncDeclaration fd = func; fd; fd = fd.toParentDecl().isFuncDeclaration())
1201
                {
1202 1
                    if ((cast(TypeFunction)fd.type).iswild)
1203
                    {
1204 1
                        isWild = true;
1205 1
                        break;
1206
                    }
1207
                }
1208 1
                if (!isWild)
1209
                {
1210 1
                    dsym.error("`inout` variables can only be declared inside `inout` functions");
1211
                }
1212
            }
1213
        }
1214

1215 1
        if (!(dsym.storage_class & (STC.ctfe | STC.ref_ | STC.result)) &&
1216 1
            tbn.ty == Tstruct && (cast(TypeStruct)tbn).sym.noDefaultCtor)
1217
        {
1218 1
            if (!dsym._init)
1219
            {
1220 1
                if (dsym.isField())
1221
                {
1222
                    /* For fields, we'll check the constructor later to make sure it is initialized
1223
                     */
1224 1
                    dsym.storage_class |= STC.nodefaultctor;
1225
                }
1226 1
                else if (dsym.storage_class & STC.parameter)
1227
                {
1228
                }
1229
                else
1230 1
                    dsym.error("default construction is disabled for type `%s`", dsym.type.toChars());
1231
            }
1232
        }
1233

1234 1
        FuncDeclaration fd = parent.isFuncDeclaration();
1235 1
        if (dsym.type.isscope() && !(dsym.storage_class & STC.nodtor))
1236
        {
1237 1
            if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.tls | STC.gshared) || !fd)
1238
            {
1239 0
                dsym.error("globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`");
1240
            }
1241

1242
            // @@@DEPRECATED@@@  https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
1243
            // Deprecated in 2.087
1244
            // Remove this when the feature is removed from the language
1245 1
            if (0 &&          // deprecation disabled for now to accommodate existing extensive use
1246
               !(dsym.storage_class & STC.scope_))
1247
            {
1248 0
                if (!(dsym.storage_class & STC.parameter) && dsym.ident != Id.withSym)
1249 0
                    dsym.error("reference to `scope class` must be `scope`");
1250
            }
1251
        }
1252

1253
        // Calculate type size + safety checks
1254 1
        if (sc.func && !sc.intypeof)
1255
        {
1256 1
            if (dsym._init && dsym._init.isVoidInitializer() && dsym.type.hasPointers()) // get type size
1257
            {
1258 1
                if (sc.func.setUnsafe())
1259 1
                    dsym.error("`void` initializers for pointers not allowed in safe functions");
1260
            }
1261 1
            else if (!dsym._init &&
1262 1
                     !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
1263 1
                     dsym.type.hasVoidInitPointers())
1264
            {
1265 1
                if (sc.func.setUnsafe())
1266 1
                    dsym.error("`void` initializers for pointers not allowed in safe functions");
1267
            }
1268
        }
1269

1270 1
        if ((!dsym._init || dsym._init.isVoidInitializer) && !fd)
1271
        {
1272
            // If not mutable, initializable by constructor only
1273 1
            dsym.storage_class |= STC.ctorinit;
1274
        }
1275

1276 1
        if (dsym._init)
1277 1
            dsym.storage_class |= STC.init; // remember we had an explicit initializer
1278 1
        else if (dsym.storage_class & STC.manifest)
1279 0
            dsym.error("manifest constants must have initializers");
1280

1281 1
        bool isBlit = false;
1282 1
        d_uns64 sz;
1283 1
        if (!dsym._init &&
1284 1
            !(dsym.storage_class & (STC.static_ | STC.gshared | STC.extern_)) &&
1285 1
            fd &&
1286 1
            (!(dsym.storage_class & (STC.field | STC.in_ | STC.foreach_ | STC.parameter | STC.result)) ||
1287 1
             (dsym.storage_class & STC.out_)) &&
1288 1
            (sz = dsym.type.size()) != 0)
1289
        {
1290
            // Provide a default initializer
1291

1292
            //printf("Providing default initializer for '%s'\n", toChars());
1293 1
            if (sz == SIZE_INVALID && dsym.type.ty != Terror)
1294 1
                dsym.error("size of type `%s` is invalid", dsym.type.toChars());
1295

1296 1
            Type tv = dsym.type;
1297 1
            while (tv.ty == Tsarray)    // Don't skip Tenum
1298 1
                tv = tv.nextOf();
1299 1
            if (tv.needsNested())
1300
            {
1301
                /* Nested struct requires valid enclosing frame pointer.
1302
                 * In StructLiteralExp::toElem(), it's calculated.
1303
                 */
1304 1
                assert(tbn.ty == Tstruct);
1305 1
                checkFrameAccess(dsym.loc, sc, tbn.isTypeStruct().sym);
1306

1307 1
                Expression e = tv.defaultInitLiteral(dsym.loc);
1308 1
                e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1309 1
                e = e.expressionSemantic(sc);
1310 1
                dsym._init = new ExpInitializer(dsym.loc, e);
1311 1
                goto Ldtor;
1312
            }
1313 1
            if (tv.ty == Tstruct && (cast(TypeStruct)tv).sym.zeroInit)
1314
            {
1315
                /* If a struct is all zeros, as a special case
1316
                 * set it's initializer to the integer 0.
1317
                 * In AssignExp::toElem(), we check for this and issue
1318
                 * a memset() to initialize the struct.
1319
                 * Must do same check in interpreter.
1320
                 */
1321 1
                Expression e = IntegerExp.literal!0;
1322 1
                e = new BlitExp(dsym.loc, new VarExp(dsym.loc, dsym), e);
1323 1
                e.type = dsym.type;      // don't type check this, it would fail
1324 1
                dsym._init = new ExpInitializer(dsym.loc, e);
1325 1
                goto Ldtor;
1326
            }
1327 1
            if (dsym.type.baseElemOf().ty == Tvoid)
1328
            {
1329 1
                dsym.error("`%s` does not have a default initializer", dsym.type.toChars());
1330
            }
1331 1
            else if (auto e = dsym.type.defaultInit(dsym.loc))
1332
            {
1333 1
                dsym._init = new ExpInitializer(dsym.loc, e);
1334
            }
1335

1336
            // Default initializer is always a blit
1337 1
            isBlit = true;
1338
        }
1339 1
        if (dsym._init)
1340
        {
1341 1
            sc = sc.push();
1342 1
            sc.stc &= ~(STC.TYPECTOR | STC.pure_ | STC.nothrow_ | STC.nogc | STC.ref_ | STC.disable);
1343

1344 1
            ExpInitializer ei = dsym._init.isExpInitializer();
1345 1
            if (ei) // https://issues.dlang.org/show_bug.cgi?id=13424
1346
                    // Preset the required type to fail in FuncLiteralDeclaration::semantic3
1347 1
                ei.exp = inferType(ei.exp, dsym.type);
1348

1349
            // If inside function, there is no semantic3() call
1350 1
            if (sc.func || sc.intypeof == 1)
1351
            {
1352
                // If local variable, use AssignExp to handle all the various
1353
                // possibilities.
1354 1
                if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.tls | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
1355
                {
1356
                    //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
1357 1
                    if (!ei)
1358
                    {
1359 1
                        ArrayInitializer ai = dsym._init.isArrayInitializer();
1360 1
                        Expression e;
1361 1
                        if (ai && tb.ty == Taarray)
1362 1
                            e = ai.toAssocArrayLiteral();
1363
                        else
1364 1
                            e = dsym._init.initializerToExpression();
1365 1
                        if (!e)
1366
                        {
1367
                            // Run semantic, but don't need to interpret
1368 1
                            dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITnointerpret);
1369 1
                            e = dsym._init.initializerToExpression();
1370 1
                            if (!e)
1371
                            {
1372 0
                                dsym.error("is not a static and cannot have static initializer");
1373 0
                                e = ErrorExp.get();
1374
                            }
1375
                        }
1376 1
                        ei = new ExpInitializer(dsym._init.loc, e);
1377 1
                        dsym._init = ei;
1378
                    }
1379

1380 1
                    Expression exp = ei.exp;
1381 1
                    Expression e1 = new VarExp(dsym.loc, dsym);
1382 1
                    if (isBlit)
1383 1
                        exp = new BlitExp(dsym.loc, e1, exp);
1384
                    else
1385 1
                        exp = new ConstructExp(dsym.loc, e1, exp);
1386 1
                    dsym.canassign++;
1387 1
                    exp = exp.expressionSemantic(sc);
1388 1
                    dsym.canassign--;
1389 1
                    exp = exp.optimize(WANTvalue);
1390 1
                    if (exp.op == TOK.error)
1391
                    {
1392 1
                        dsym._init = new ErrorInitializer();
1393 1
                        ei = null;
1394
                    }
1395
                    else
1396 1
                        ei.exp = exp;
1397

1398 1
                    if (ei && dsym.isScope())
1399
                    {
1400 1
                        Expression ex = ei.exp.lastComma();
1401 1
                        if (ex.op == TOK.blit || ex.op == TOK.construct)
1402 1
                            ex = (cast(AssignExp)ex).e2;
1403 1
                        if (ex.op == TOK.new_)
1404
                        {
1405
                            // See if initializer is a NewExp that can be allocated on the stack
1406 1
                            NewExp ne = cast(NewExp)ex;
1407 1
                            if (dsym.type.toBasetype().ty == Tclass)
1408
                            {
1409 1
                                if (ne.newargs && ne.newargs.dim > 1)
1410
                                {
1411 0
                                    dsym.mynew = true;
1412
                                }
1413
                                else
1414
                                {
1415 1
                                    ne.onstack = 1;
1416 1
                                    dsym.onstack = true;
1417
                                }
1418
                            }
1419
                        }
1420 1
                        else if (ex.op == TOK.function_)
1421
                        {
1422
                            // or a delegate that doesn't escape a reference to the function
1423 1
                            FuncDeclaration f = (cast(FuncExp)ex).fd;
1424 1
                            if (f.tookAddressOf)
1425 0
                                f.tookAddressOf--;
1426
                        }
1427
                    }
1428
                }
1429
                else
1430
                {
1431
                    // https://issues.dlang.org/show_bug.cgi?id=14166
1432
                    // Don't run CTFE for the temporary variables inside typeof
1433 1
                    dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret);
1434 1
                    const init_err = dsym._init.isExpInitializer();
1435 1
                    if (init_err && init_err.exp.op == TOK.showCtfeContext)
1436
                    {
1437 1
                         errorSupplemental(dsym.loc, "compile time context created here");
1438
                    }
1439
                }
1440
            }
1441 1
            else if (parent.isAggregateDeclaration())
1442
            {
1443 1
                dsym._scope = scx ? scx : sc.copy();
1444 1
                dsym._scope.setNoFree();
1445
            }
1446 1
            else if (dsym.storage_class & (STC.const_ | STC.immutable_ | STC.manifest) || dsym.type.isConst() || dsym.type.isImmutable())
1447
            {
1448
                /* Because we may need the results of a const declaration in a
1449
                 * subsequent type, such as an array dimension, before semantic2()
1450
                 * gets ordinarily run, try to run semantic2() now.
1451
                 * Ignore failure.
1452
                 */
1453 1
                if (!inferred)
1454
                {
1455 1
                    uint errors = global.errors;
1456 1
                    dsym.inuse++;
1457
                    // Bug 20549. Don't try this on modules or packages, syntaxCopy
1458
                    // could crash (inf. recursion) on a mod/pkg referencing itself
1459 1
                    if (ei && (ei.exp.op != TOK.scope_ ? true : !(cast(ScopeExp)ei.exp).sds.isPackage()))
1460
                    {
1461 1
                        Expression exp = ei.exp.syntaxCopy();
1462

1463 1
                        bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
1464 1
                        if (needctfe)
1465 1
                            sc = sc.startCTFE();
1466 1
                        exp = exp.expressionSemantic(sc);
1467 1
                        exp = resolveProperties(sc, exp);
1468 1
                        if (needctfe)
1469 1
                            sc = sc.endCTFE();
1470

1471 1
                        Type tb2 = dsym.type.toBasetype();
1472 1
                        Type ti = exp.type.toBasetype();
1473

1474
                        /* The problem is the following code:
1475
                         *  struct CopyTest {
1476
                         *     double x;
1477
                         *     this(double a) { x = a * 10.0;}
1478
                         *     this(this) { x += 2.0; }
1479
                         *  }
1480
                         *  const CopyTest z = CopyTest(5.3);  // ok
1481
                         *  const CopyTest w = z;              // not ok, postblit not run
1482
                         *  static assert(w.x == 55.0);
1483
                         * because the postblit doesn't get run on the initialization of w.
1484
                         */
1485 1
                        if (auto ts = ti.isTypeStruct())
1486
                        {
1487 1
                            StructDeclaration sd = ts.sym;
1488
                            /* Look to see if initializer involves a copy constructor
1489
                             * (which implies a postblit)
1490
                             */
1491
                            // there is a copy constructor
1492
                            // and exp is the same struct
1493 1
                            if (sd.postblit && tb2.toDsymbol(null) == sd)
1494
                            {
1495
                                // The only allowable initializer is a (non-copy) constructor
1496 1
                                if (exp.isLvalue())
1497 1
                                    dsym.error("of type struct `%s` uses `this(this)`, which is not allowed in static initialization", tb2.toChars());
1498
                            }
1499
                        }
1500 1
                        ei.exp = exp;
1501
                    }
1502 1
                    dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
1503 1
                    dsym.inuse--;
1504 1
                    if (global.errors > errors)
1505
                    {
1506 1
                        dsym._init = new ErrorInitializer();
1507 1
                        dsym.type = Type.terror;
1508
                    }
1509
                }
1510
                else
1511
                {
1512 1
                    dsym._scope = scx ? scx : sc.copy();
1513 1
                    dsym._scope.setNoFree();
1514
                }
1515
            }
1516 1
            sc = sc.pop();
1517
        }
1518

1519
    Ldtor:
1520
        /* Build code to execute destruction, if necessary
1521
         */
1522 1
        dsym.edtor = dsym.callScopeDtor(sc);
1523 1
        if (dsym.edtor)
1524
        {
1525
            /* If dsym is a local variable, who's type is a struct with a scope destructor,
1526
             * then make dsym scope, too.
1527
             */
1528 1
            if (global.params.vsafe &&
1529 1
                !(dsym.storage_class & (STC.parameter | STC.temp | STC.field | STC.in_ | STC.foreach_ | STC.result | STC.manifest)) &&
1530 1
                !dsym.isDataseg() &&
1531 1
                !dsym.doNotInferScope &&
1532 1
                dsym.type.hasPointers())
1533
            {
1534 1
                auto tv = dsym.type.baseElemOf();
1535 1
                if (tv.ty == Tstruct &&
1536 1
                    (cast(TypeStruct)tv).sym.dtor.storage_class & STC.scope_)
1537
                {
1538 1
                    dsym.storage_class |= STC.scope_;
1539
                }
1540
            }
1541

1542 1
            if (sc.func && dsym.storage_class & (STC.static_ | STC.gshared))
1543 1
                dsym.edtor = dsym.edtor.expressionSemantic(sc._module._scope);
1544
            else
1545 1
                dsym.edtor = dsym.edtor.expressionSemantic(sc);
1546

1547
            version (none)
1548
            {
1549
                // currently disabled because of std.stdio.stdin, stdout and stderr
1550
                if (dsym.isDataseg() && !(dsym.storage_class & STC.extern_))
1551
                    dsym.error("static storage variables cannot have destructors");
1552
            }
1553
        }
1554

1555 1
        dsym.semanticRun = PASS.semanticdone;
1556

1557 1
        if (dsym.type.toBasetype().ty == Terror)
1558 1
            dsym.errors = true;
1559

1560 1
        if(sc.scopesym && !sc.scopesym.isAggregateDeclaration())
1561
        {
1562 1
            for (ScopeDsymbol sym = sc.scopesym; sym && dsym.endlinnum == 0;
1563 1
                 sym = sym.parent ? sym.parent.isScopeDsymbol() : null)
1564 1
                dsym.endlinnum = sym.endlinnum;
1565
        }
1566
    }
1567

1568
    override void visit(TypeInfoDeclaration dsym)
1569
    {
1570 1
        assert(dsym.linkage == LINK.c);
1571
    }
1572

1573
    override void visit(Import imp)
1574
    {
1575
        //printf("Import::semantic('%s') %s\n", toPrettyChars(), id.toChars());
1576 1
        if (imp.semanticRun > PASS.init)
1577 1
            return;
1578

1579 1
        if (imp._scope)
1580
        {
1581 1
            sc = imp._scope;
1582 1
            imp._scope = null;
1583
        }
1584 1
        if (!sc)
1585 0
            return;
1586

1587 1
        imp.semanticRun = PASS.semantic;
1588

1589
        // Load if not already done so
1590 1
        bool loadErrored = false;
1591 1
        if (!imp.mod)
1592
        {
1593 1
            loadErrored = imp.load(sc);
1594 1
            if (imp.mod)
1595
            {
1596 1
                imp.mod.importAll(null);
1597 1
                imp.mod.checkImportDeprecation(imp.loc, sc);
1598
            }
1599
        }
1600 1
        if (imp.mod)
1601
        {
1602
            // Modules need a list of each imported module
1603

1604
            // if inside a template instantiation, the instantianting
1605
            // module gets the import.
1606
            // https://issues.dlang.org/show_bug.cgi?id=17181
1607 1
            Module importer = sc._module;
1608 1
            if (sc.minst && sc.tinst)
1609
            {
1610 1
                importer = sc.minst;
1611 1
                if (!sc.tinst.importedModules.contains(imp.mod))
1612 1
                    sc.tinst.importedModules.push(imp.mod);
1613
            }
1614
            //printf("%s imports %s\n", importer.toChars(), imp.mod.toChars());
1615 1
            if (!importer.aimports.contains(imp.mod))
1616 1
                importer.aimports.push(imp.mod);
1617

1618 1
            if (sc.explicitProtection)
1619 1
                imp.protection = sc.protection;
1620

1621 1
            if (!imp.aliasId && !imp.names.dim) // neither a selective nor a renamed import
1622
            {
1623 1
                ScopeDsymbol scopesym;
1624 1
                for (Scope* scd = sc; scd; scd = scd.enclosing)
1625
                {
1626 1
                    if (!scd.scopesym)
1627 1
                        continue;
1628 1
                    scopesym = scd.scopesym;
1629 1
                    break;
1630
                }
1631

1632 1
                if (!imp.isstatic)
1633
                {
1634 1
                    scopesym.importScope(imp.mod, imp.protection);
1635
                }
1636

1637
                // Mark the imported packages as accessible from the current
1638
                // scope. This access check is necessary when using FQN b/c
1639
                // we're using a single global package tree.
1640
                // https://issues.dlang.org/show_bug.cgi?id=313
1641 1
                if (imp.packages)
1642
                {
1643
                    // import a.b.c.d;
1644 1
                    auto p = imp.pkg; // a
1645 1
                    scopesym.addAccessiblePackage(p, imp.protection);
1646 1
                    foreach (id; (*imp.packages)[1 .. imp.packages.dim]) // [b, c]
1647
                    {
1648 1
                        p = cast(Package) p.symtab.lookup(id);
1649
                        // https://issues.dlang.org/show_bug.cgi?id=17991
1650
                        // An import of truly empty file/package can happen
1651
                        // https://issues.dlang.org/show_bug.cgi?id=20151
1652
                        // Package in the path conflicts with a module name
1653 1
                        if (p is null)
1654 1
                            break;
1655 1
                        scopesym.addAccessiblePackage(p, imp.protection);
1656
                    }
1657
                }
1658 1
                scopesym.addAccessiblePackage(imp.mod, imp.protection); // d
1659
            }
1660

1661 1
            if (!loadErrored)
1662
            {
1663 1
                imp.mod.dsymbolSemantic(null);
1664
            }
1665

1666 1
            if (imp.mod.needmoduleinfo)
1667
            {
1668
                //printf("module4 %s because of %s\n", importer.toChars(), imp.mod.toChars());
1669 1
                importer.needmoduleinfo = 1;
1670
            }
1671

1672 1
            sc = sc.push(imp.mod);
1673 1
            sc.protection = imp.protection;
1674 1
            for (size_t i = 0; i < imp.aliasdecls.dim; i++)
1675
            {
1676 1
                AliasDeclaration ad = imp.aliasdecls[i];
1677
                //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), aliases[i].toChars(), names[i].toChars(), ad._scope);
1678 1
                Dsymbol sym = imp.mod.search(imp.loc, imp.names[i], IgnorePrivateImports);
1679 1
                if (sym)
1680
                {
1681
                    import dmd.access : symbolIsVisible;
1682 1
                    if (!symbolIsVisible(sc, sym))
1683 1
                        imp.mod.error(imp.loc, "member `%s` is not visible from module `%s`",
1684
                            imp.names[i].toChars(), sc._module.toChars());
1685 1
                    ad.dsymbolSemantic(sc);
1686
                    // If the import declaration is in non-root module,
1687
                    // analysis of the aliased symbol is deferred.
1688
                    // Therefore, don't see the ad.aliassym or ad.type here.
1689
                }
1690
                else
1691
                {
1692 1
                    Dsymbol s = imp.mod.search_correct(imp.names[i]);
1693 1
                    if (s)
1694 1
                        imp.mod.error(imp.loc, "import `%s` not found, did you mean %s `%s`?", imp.names[i].toChars(), s.kind(), s.toPrettyChars());
1695
                    else
1696 1
                        imp.mod.error(imp.loc, "import `%s` not found", imp.names[i].toChars());
1697 1
                    ad.type = Type.terror;
1698
                }
1699
            }
1700 1
            sc = sc.pop();
1701
        }
1702

1703 1
        imp.semanticRun = PASS.semanticdone;
1704

1705
        // object self-imports itself, so skip that
1706
        // https://issues.dlang.org/show_bug.cgi?id=7547
1707
        // don't list pseudo modules __entrypoint.d, __main.d
1708
        // https://issues.dlang.org/show_bug.cgi?id=11117
1709
        // https://issues.dlang.org/show_bug.cgi?id=11164
1710 1
        if (global.params.moduleDeps !is null && !(imp.id == Id.object && sc._module.ident == Id.object) &&
1711 1
            strcmp(sc._module.ident.toChars(), "__main") != 0)
1712
        {
1713
            /* The grammar of the file is:
1714
             *      ImportDeclaration
1715
             *          ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
1716
             *      ModuleAliasIdentifier ] "\n"
1717
             *
1718
             *      BasicImportDeclaration
1719
             *          ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
1720
             *              " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
1721
             *
1722
             *      FilePath
1723
             *          - any string with '(', ')' and '\' escaped with the '\' character
1724
             */
1725 1
            OutBuffer* ob = global.params.moduleDeps;
1726 1
            Module imod = sc.instantiatingModule();
1727 1
            if (!global.params.moduleDepsFile)
1728 1
                ob.writestring("depsImport ");
1729 1
            ob.writestring(imod.toPrettyChars());
1730 1
            ob.writestring(" (");
1731 1
            escapePath(ob, imod.srcfile.toChars());
1732 1
            ob.writestring(") : ");
1733
            // use protection instead of sc.protection because it couldn't be
1734
            // resolved yet, see the comment above
1735 1
            protectionToBuffer(ob, imp.protection);
1736 1
            ob.writeByte(' ');
1737 1
            if (imp.isstatic)
1738
            {
1739 0
                stcToBuffer(ob, STC.static_);
1740 0
                ob.writeByte(' ');
1741
            }
1742 1
            ob.writestring(": ");
1743 1
            if (imp.packages)
1744
            {
1745 1
                for (size_t i = 0; i < imp.packages.dim; i++)
1746
                {
1747 1
                    Identifier pid = (*imp.packages)[i];
1748 1
                    ob.printf("%s.", pid.toChars());
1749
                }
1750
            }
1751 1
            ob.writestring(imp.id.toString());
1752 1
            ob.writestring(" (");
1753 1
            if (imp.mod)
1754 1
                escapePath(ob, imp.mod.srcfile.toChars());
1755
            else
1756 0
                ob.writestring("???");
1757 1
            ob.writeByte(')');
1758 1
            foreach (i, name; imp.names)
1759
            {
1760 1
                if (i == 0)
1761 1
                    ob.writeByte(':');
1762
                else
1763 1
                    ob.writeByte(',');
1764 1
                Identifier _alias = imp.aliases[i];
1765 1
                if (!_alias)
1766
                {
1767 1
                    ob.printf("%s", name.toChars());
1768 1
                    _alias = name;
1769
                }
1770
                else
1771 0
                    ob.printf("%s=%s", _alias.toChars(), name.toChars());
1772
            }
1773 1
            if (imp.aliasId)
1774 0
                ob.printf(" -> %s", imp.aliasId.toChars());
1775 1
            ob.writenl();
1776
        }
1777
        //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
1778
    }
1779

1780
    void attribSemantic(AttribDeclaration ad)
1781
    {
1782 1
        if (ad.semanticRun != PASS.init)
1783 1
            return;
1784 1
        ad.semanticRun = PASS.semantic;
1785 1
        Dsymbols* d = ad.include(sc);
1786
        //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
1787 1
        if (d)
1788
        {
1789 1
            Scope* sc2 = ad.newScope(sc);
1790 1
            bool errors;
1791 1
            for (size_t i = 0; i < d.dim; i++)
1792
            {
1793 1
                Dsymbol s = (*d)[i];
1794 1
                s.dsymbolSemantic(sc2);
1795 1
                errors |= s.errors;
1796
            }
1797 1
            ad.errors |= errors;
1798 1
            if (sc2 != sc)
1799 1
                sc2.pop();
1800
        }
1801 1
        ad.semanticRun = PASS.semanticdone;
1802
    }
1803

1804
    override void visit(AttribDeclaration atd)
1805
    {
1806 1
        attribSemantic(atd);
1807
    }
1808

1809
    override void visit(AnonDeclaration scd)
1810
    {
1811
        //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
1812 1
        assert(sc.parent);
1813 1
        auto p = sc.parent.pastMixin();
1814 1
        auto ad = p.isAggregateDeclaration();
1815 1
        if (!ad)
1816
        {
1817 1
            error(scd.loc, "%s can only be a part of an aggregate, not %s `%s`", scd.kind(), p.kind(), p.toChars());
1818 1
            scd.errors = true;
1819 1
            return;
1820
        }
1821

1822 1
        if (scd.decl)
1823
        {
1824 1
            sc = sc.push();
1825 1
            sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.tls | STC.gshared);
1826 1
            sc.inunion = scd.isunion ? scd : null;
1827 1
            sc.flags = 0;
1828 1
            for (size_t i = 0; i < scd.decl.dim; i++)
1829
            {
1830 1
                Dsymbol s = (*scd.decl)[i];
1831 1
                s.dsymbolSemantic(sc);
1832
            }
1833 1
            sc = sc.pop();
1834
        }
1835
    }
1836

1837
    override void visit(PragmaDeclaration pd)
1838
    {
1839
        // Should be merged with PragmaStatement
1840
        //printf("\tPragmaDeclaration::semantic '%s'\n", pd.toChars());
1841 1
        if (global.params.mscoff)
1842
        {
1843 0
            if (pd.ident == Id.linkerDirective)
1844
            {
1845 0
                if (!pd.args || pd.args.dim != 1)
1846 0
                    pd.error("one string argument expected for pragma(linkerDirective)");
1847
                else
1848
                {
1849 0
                    auto se = semanticString(sc, (*pd.args)[0], "linker directive");
1850 0
                    if (!se)
1851 0
                        goto Lnodecl;
1852 0
                    (*pd.args)[0] = se;
1853 0
                    if (global.params.verbose)
1854 0
                        message("linkopt   %.*s", cast(int)se.len, se.peekString().ptr);
1855
                }
1856 0
                goto Lnodecl;
1857
            }
1858
        }
1859 1
        if (pd.ident == Id.msg)
1860
        {
1861 1
            if (pd.args)
1862
            {
1863 1
                for (size_t i = 0; i < pd.args.dim; i++)
1864
                {
1865 1
                    Expression e = (*pd.args)[i];
1866 1
                    sc = sc.startCTFE();
1867 1
                    e = e.expressionSemantic(sc);
1868 1
                    e = resolveProperties(sc, e);
1869 1
                    sc = sc.endCTFE();
1870
                    // pragma(msg) is allowed to contain types as well as expressions
1871 1
                    if (e.type && e.type.ty == Tvoid)
1872
                    {
1873 1
                        error(pd.loc, "Cannot pass argument `%s` to `pragma msg` because it is `void`", e.toChars());
1874 1
                        return;
1875
                    }
1876 1
                    e = ctfeInterpretForPragmaMsg(e);
1877 1
                    if (e.op == TOK.error)
1878
                    {
1879 1
                        errorSupplemental(pd.loc, "while evaluating `pragma(msg, %s)`", (*pd.args)[i].toChars());
1880 1
                        return;
1881
                    }
1882 1
                    StringExp se = e.toStringExp();
1883 1
                    if (se)
1884
                    {
1885 1
                        se = se.toUTF8(sc);
1886 1
                        fprintf(stderr, "%.*s", cast(int)se.len, se.peekString().ptr);
1887
                    }
1888
                    else
1889 1
                        fprintf(stderr, "%s", e.toChars());
1890
                }
1891 1
                fprintf(stderr, "\n");
1892
            }
1893 1
            goto Lnodecl;
1894
        }
1895 1
        else if (pd.ident == Id.lib)
1896
        {
1897 1
            if (!pd.args || pd.args.dim != 1)
1898 0
                pd.error("string expected for library name");
1899
            else
1900
            {
1901 1
                auto se = semanticString(sc, (*pd.args)[0], "library name");
1902 1
                if (!se)
1903 0
                    goto Lnodecl;
1904 1
                (*pd.args)[0] = se;
1905

1906 1
                auto name = se.peekString().xarraydup;
1907 1
                if (global.params.verbose)
1908 0
                    message("library   %s", name.ptr);
1909 1
                if (global.params.moduleDeps && !global.params.moduleDepsFile)
1910
                {
1911 0
                    OutBuffer* ob = global.params.moduleDeps;
1912 0
                    Module imod = sc.instantiatingModule();
1913 0
                    ob.writestring("depsLib ");
1914 0
                    ob.writestring(imod.toPrettyChars());
1915 0
                    ob.writestring(" (");
1916 0
                    escapePath(ob, imod.srcfile.toChars());
1917 0
                    ob.writestring(") : ");
1918 0
                    ob.writestring(name);
1919 0
                    ob.writenl();
1920
                }
1921 1
                mem.xfree(name.ptr);
1922
            }
1923 1
            goto Lnodecl;
1924
        }
1925 1
        else if (pd.ident == Id.startaddress)
1926
        {
1927 1
            if (!pd.args || pd.args.dim != 1)
1928 0
                pd.error("function name expected for start address");
1929
            else
1930
            {
1931
                /* https://issues.dlang.org/show_bug.cgi?id=11980
1932
                 * resolveProperties and ctfeInterpret call are not necessary.
1933
                 */
1934 1
                Expression e = (*pd.args)[0];
1935 1
                sc = sc.startCTFE();
1936 1
                e = e.expressionSemantic(sc);
1937 1
                sc = sc.endCTFE();
1938 1
                (*pd.args)[0] = e;
1939 1
                Dsymbol sa = getDsymbol(e);
1940 1
                if (!sa || !sa.isFuncDeclaration())
1941 0
                    pd.error("function name expected for start address, not `%s`", e.toChars());
1942
            }
1943 1
            goto Lnodecl;
1944
        }
1945 1
        else if (pd.ident == Id.Pinline)
1946
        {
1947 1
            goto Ldecl;
1948
        }
1949 1
        else if (pd.ident == Id.mangle)
1950
        {
1951 1
            if (!pd.args)
1952 1
                pd.args = new Expressions();
1953 1
            if (pd.args.dim != 1)
1954
            {
1955 1
                pd.error("string expected for mangled name");
1956 1
                pd.args.setDim(1);
1957 1
                (*pd.args)[0] = ErrorExp.get(); // error recovery
1958 1
                goto Ldecl;
1959
            }
1960

1961 1
            auto se = semanticString(sc, (*pd.args)[0], "mangled name");
1962 1
            if (!se)
1963 1
                goto Ldecl;
1964 1
            (*pd.args)[0] = se; // Will be used later
1965

1966 1
            if (!se.len)
1967
            {
1968 1
                pd.error("zero-length string not allowed for mangled name");
1969 1
                goto Ldecl;
1970
            }
1971 1
            if (se.sz != 1)
1972
            {
1973 1
                pd.error("mangled name characters can only be of type `char`");
1974 1
                goto Ldecl;
1975
            }
1976
            version (all)
1977
            {
1978
                /* Note: D language specification should not have any assumption about backend
1979
                 * implementation. Ideally pragma(mangle) can accept a string of any content.
1980
                 *
1981
                 * Therefore, this validation is compiler implementation specific.
1982
                 */
1983 1
                auto slice = se.peekString();
1984 1
                for (size_t i = 0; i < se.len;)
1985
                {
1986 1
                    dchar c = slice[i];
1987 1
                    if (c < 0x80)
1988
                    {
1989 1
                        if (c.isValidMangling)
1990
                        {
1991 1
                            ++i;
1992 1
                            continue;
1993
                        }
1994
                        else
1995
                        {
1996 1
                            pd.error("char 0x%02x not allowed in mangled name", c);
1997 1
                            break;
1998
                        }
1999
                    }
2000 1
                    if (const msg = utf_decodeChar(slice, i, c))
2001
                    {
2002 1
                        pd.error("%.*s", cast(int)msg.length, msg.ptr);
2003 1
                        break;
2004
                    }
2005 1
                    if (!isUniAlpha(c))
2006
                    {
2007 0
                        pd.error("char `0x%04x` not allowed in mangled name", c);
2008 0
                        break;
2009
                    }
2010
                }
2011
            }
2012
        }
2013 1
        else if (pd.ident == Id.crt_constructor || pd.ident == Id.crt_destructor)
2014
        {
2015 1
            if (pd.args && pd.args.dim != 0)
2016 1
                pd.error("takes no argument");
2017 1
            goto Ldecl;
2018
        }
2019 1
        else if (pd.ident == Id.printf || pd.ident == Id.scanf)
2020
        {
2021 1
            if (pd.args && pd.args.dim != 0)
2022 0
                pd.error("takes no argument");
2023 1
            goto Ldecl;
2024
        }
2025 1
        else if (global.params.ignoreUnsupportedPragmas)
2026
        {
2027 1
            if (global.params.verbose)
2028
            {
2029
                /* Print unrecognized pragmas
2030
                 */
2031 1
                OutBuffer buf;
2032 1
                buf.writestring(pd.ident.toString());
2033 1
                if (pd.args)
2034
                {
2035 1
                    const errors_save = global.startGagging();
2036 1
                    for (size_t i = 0; i < pd.args.dim; i++)
2037
                    {
2038 1
                        Expression e = (*pd.args)[i];
2039 1
                        sc = sc.startCTFE();
2040 1
                        e = e.expressionSemantic(sc);
2041 1
                        e = resolveProperties(sc, e);
2042 1
                        sc = sc.endCTFE();
2043 1
                        e = e.ctfeInterpret();
2044 1
                        if (i == 0)
2045 1
                            buf.writestring(" (");
2046
                        else
2047 0
                            buf.writeByte(',');
2048 1
                        buf.writestring(e.toChars());
2049
                    }
2050 1
                    if (pd.args.dim)
2051 1
                        buf.writeByte(')');
2052 1
                    global.endGagging(errors_save);
2053
                }
2054 1
                message("pragma    %s", buf.peekChars());
2055
            }
2056
        }
2057
        else
2058 0
            error(pd.loc, "unrecognized `pragma(%s)`", pd.ident.toChars());
2059
    Ldecl:
2060 1
        if (pd.decl)
2061
        {
2062 1
            Scope* sc2 = pd.newScope(sc);
2063 1
            for (size_t i = 0; i < pd.decl.dim; i++)
2064
            {
2065 1
                Dsymbol s = (*pd.decl)[i];
2066 1
                s.dsymbolSemantic(sc2);
2067 1
                if (pd.ident == Id.mangle)
2068
                {
2069 1
                    assert(pd.args && pd.args.dim == 1);
2070 1
                    if (auto se = (*pd.args)[0].toStringExp())
2071
                    {
2072 1
                        const name = (cast(const(char)[])se.peekData()).xarraydup;
2073 1
                        uint cnt = setMangleOverride(s, name);
2074 1
                        if (cnt > 1)
2075 1
                            pd.error("can only apply to a single declaration");
2076
                    }
2077
                }
2078
            }
2079 1
            if (sc2 != sc)
2080 1
                sc2.pop();
2081
        }
2082 1
        return;
2083
    Lnodecl:
2084 1
        if (pd.decl)
2085
        {
2086 1
            pd.error("is missing a terminating `;`");
2087 1
            goto Ldecl;
2088
            // do them anyway, to avoid segfaults.
2089
        }
2090
    }
2091

2092
    override void visit(StaticIfDeclaration sid)
2093
    {
2094 1
        attribSemantic(sid);
2095
    }
2096

2097
    override void visit(StaticForeachDeclaration sfd)
2098
    {
2099 1
        attribSemantic(sfd);
2100
    }
2101

2102
    private Dsymbols* compileIt(CompileDeclaration cd)
2103
    {
2104
        //printf("CompileDeclaration::compileIt(loc = %d) %s\n", cd.loc.linnum, cd.exp.toChars());
2105 1
        OutBuffer buf;
2106 1
        if (expressionsToString(buf, sc, cd.exps))
2107 1
            return null;
2108

2109 1
        const errors = global.errors;
2110 1
        const len = buf.length;
2111 1
        buf.writeByte(0);
2112 1
        const str = buf.extractSlice()[0 .. len];
2113 1
        scope p = new Parser!ASTCodegen(cd.loc, sc._module, str, false);
2114 1
        p.nextToken();
2115

2116 1
        auto d = p.parseDeclDefs(0);
2117 1
        if (global.errors != errors)
2118 1
            return null;
2119

2120 1
        if (p.token.value != TOK.endOfFile)
2121
        {
2122 0
            cd.error("incomplete mixin declaration `%s`", str.ptr);
2123 0
            return null;
2124
        }
2125 1
        return d;
2126
    }
2127

2128
    /***********************************************************
2129
     * https://dlang.org/spec/module.html#mixin-declaration
2130
     */
2131
    override void visit(CompileDeclaration cd)
2132
    {
2133
        //printf("CompileDeclaration::semantic()\n");
2134 1
        if (!cd.compiled)
2135
        {
2136 1
            cd.decl = compileIt(cd);
2137 1
            cd.AttribDeclaration.addMember(sc, cd.scopesym);
2138 1
            cd.compiled = true;
2139

2140 1
            if (cd._scope && cd.decl)
2141
            {
2142 1
                for (size_t i = 0; i < cd.decl.dim; i++)
2143
                {
2144 1
                    Dsymbol s = (*cd.decl)[i];
2145 1
                    s.setScope(cd._scope);
2146
                }
2147
            }
2148
        }
2149 1
        attribSemantic(cd);
2150
    }
2151

2152
    override void visit(CPPNamespaceDeclaration ns)
2153
    {
2154
        Identifier identFromSE (StringExp se)
2155
        {
2156 1
            const sident = se.toStringz();
2157 1
            if (!sident.length || !Identifier.isValidIdentifier(sident))
2158
            {
2159 1
                ns.exp.error("expected valid identifer for C++ namespace but got `%.*s`",
2160
                             cast(int)sident.length, sident.ptr);
2161 1
                return null;
2162
            }
2163
            else
2164 1
                return Identifier.idPool(sident);
2165
        }
2166

2167 1
        if (ns.ident is null)
2168
        {
2169 1
            ns.cppnamespace = sc.namespace;
2170 1
            sc = sc.startCTFE();
2171 1
            ns.exp = ns.exp.expressionSemantic(sc);
2172 1
            ns.exp = resolveProperties(sc, ns.exp);
2173 1
            sc = sc.endCTFE();
2174 1
            ns.exp = ns.exp.ctfeInterpret();
2175
            // Can be either a tuple of strings or a string itself
2176 1
            if (auto te = ns.exp.isTupleExp())
2177
            {
2178 1
                expandTuples(te.exps);
2179 1
                CPPNamespaceDeclaration current = ns.cppnamespace;
2180 1
                for (size_t d = 0; d < te.exps.dim; ++d)
2181
                {
2182 1
                    auto exp = (*te.exps)[d];
2183 1
                    auto prev = d ? current : ns.cppnamespace;
2184 1
                    current = (d + 1) != te.exps.dim
2185 1
                        ? new CPPNamespaceDeclaration(exp, null)
2186 1
                        : ns;
2187 1
                    current.exp = exp;
2188 1
                    current.cppnamespace = prev;
2189 1
                    if (auto se = exp.toStringExp())
2190
                    {
2191 1
                        current.ident = identFromSE(se);
2192 1
                        if (current.ident is null)
2193 0
                            return; // An error happened in `identFromSE`
2194
                    }
2195
                    else
2196 0
                        ns.exp.error("`%s`: index %llu is not a string constant, it is a `%s`",
2197
                                     ns.exp.toChars(), cast(ulong) d, ns.exp.type.toChars());
2198
                }
2199
            }
2200 1
            else if (auto se = ns.exp.toStringExp())
2201 1
                ns.ident = identFromSE(se);
2202
            else
2203 1
                ns.exp.error("compile time string constant (or tuple) expected, not `%s`",
2204
                             ns.exp.toChars());
2205
        }
2206 1
        if (ns.ident)
2207 1
            attribSemantic(ns);
2208
    }
2209

2210
    override void visit(UserAttributeDeclaration uad)
2211
    {
2212
        //printf("UserAttributeDeclaration::semantic() %p\n", this);
2213 1
        if (uad.decl && !uad._scope)
2214 1
            uad.Dsymbol.setScope(sc); // for function local symbols
2215 1
        arrayExpressionSemantic(uad.atts, sc, true);
2216 1
        return attribSemantic(uad);
2217
    }
2218

2219
    override void visit(StaticAssert sa)
2220
    {
2221 1
        if (sa.semanticRun < PASS.semanticdone)
2222 1
            sa.semanticRun = PASS.semanticdone;
2223
    }
2224

2225
    override void visit(DebugSymbol ds)
2226
    {
2227
        //printf("DebugSymbol::semantic() %s\n", toChars());
2228 1
        if (ds.semanticRun < PASS.semanticdone)
2229 1
            ds.semanticRun = PASS.semanticdone;
2230
    }
2231

2232
    override void visit(VersionSymbol vs)
2233
    {
2234 1
        if (vs.semanticRun < PASS.semanticdone)
2235 1
            vs.semanticRun = PASS.semanticdone;
2236
    }
2237

2238
    override void visit(Package pkg)
2239
    {
2240 1
        if (pkg.semanticRun < PASS.semanticdone)
2241 1
            pkg.semanticRun = PASS.semanticdone;
2242
    }
2243

2244
    override void visit(Module m)
2245
    {
2246 1
        if (m.semanticRun != PASS.init)
2247 1
            return;
2248
        //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
2249 1
        m.semanticRun = PASS.semantic;
2250
        // Note that modules get their own scope, from scratch.
2251
        // This is so regardless of where in the syntax a module
2252
        // gets imported, it is unaffected by context.
2253 1
        Scope* sc = m._scope; // see if already got one from importAll()
2254 1
        if (!sc)
2255
        {
2256 0
            Scope.createGlobal(m); // create root scope
2257
        }
2258

2259
        //printf("Module = %p, linkage = %d\n", sc.scopesym, sc.linkage);
2260
        // Pass 1 semantic routines: do public side of the definition
2261 1
        m.members.foreachDsymbol( (s)
2262
        {
2263
            //printf("\tModule('%s'): '%s'.dsymbolSemantic()\n", toChars(), s.toChars());
2264 1
            s.dsymbolSemantic(sc);
2265 1
            m.runDeferredSemantic();
2266
        });
2267

2268 1
        if (m.userAttribDecl)
2269
        {
2270 1
            m.userAttribDecl.dsymbolSemantic(sc);
2271
        }
2272 1
        if (!m._scope)
2273
        {
2274 0
            sc = sc.pop();
2275 0
            sc.pop(); // 2 pops because Scope::createGlobal() created 2
2276
        }
2277 1
        m.semanticRun = PASS.semanticdone;
2278
        //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
2279
    }
2280

2281
    override void visit(EnumDeclaration ed)
2282
    {
2283
        //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), toChars());
2284
        //printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
2285 1
        if (ed.semanticRun >= PASS.semanticdone)
2286 1
            return; // semantic() already completed
2287 1
        if (ed.semanticRun == PASS.semantic)
2288
        {
2289 1
            assert(ed.memtype);
2290 1
            error(ed.loc, "circular reference to enum base type `%s`", ed.memtype.toChars());
2291 1
            ed.errors = true;
2292 1
            ed.semanticRun = PASS.semanticdone;
2293 1
            return;
2294
        }
2295 1
        uint dprogress_save = Module.dprogress;
2296

2297 1
        Scope* scx = null;
2298 1
        if (ed._scope)
2299
        {
2300 1
            sc = ed._scope;
2301 1
            scx = ed._scope; // save so we don't make redundant copies
2302 1
            ed._scope = null;
2303
        }
2304

2305 1
        if (!sc)
2306 0
            return;
2307

2308 1
        ed.parent = sc.parent;
2309 1
        ed.type = ed.type.typeSemantic(ed.loc, sc);
2310

2311 1
        ed.protection = sc.protection;
2312 1
        if (sc.stc & STC.deprecated_)
2313 1
            ed.isdeprecated = true;
2314 1
        ed.userAttribDecl = sc.userAttribDecl;
2315 1
        ed.cppnamespace = sc.namespace;
2316

2317 1
        ed.semanticRun = PASS.semantic;
2318 1
        UserAttributeDeclaration.checkGNUABITag(ed, sc.linkage);
2319

2320 1
        if (!ed.members && !ed.memtype) // enum ident;
2321
        {
2322 1
            ed.semanticRun = PASS.semanticdone;
2323 1
            return;
2324
        }
2325

2326 1
        if (!ed.symtab)
2327 1
            ed.symtab = new DsymbolTable();
2328

2329
        /* The separate, and distinct, cases are:
2330
         *  1. enum { ... }
2331
         *  2. enum : memtype { ... }
2332
         *  3. enum ident { ... }
2333
         *  4. enum ident : memtype { ... }
2334
         *  5. enum ident : memtype;
2335
         *  6. enum ident;
2336
         */
2337

2338 1
        if (ed.memtype)
2339
        {
2340 1
            ed.memtype = ed.memtype.typeSemantic(ed.loc, sc);
2341

2342
            /* Check to see if memtype is forward referenced
2343
             */
2344 1
            if (auto te = ed.memtype.isTypeEnum())
2345
            {
2346 1
                EnumDeclaration sym = cast(EnumDeclaration)te.toDsymbol(sc);
2347 1
                if (!sym.memtype || !sym.members || !sym.symtab || sym._scope)
2348
                {
2349
                    // memtype is forward referenced, so try again later
2350 1
                    deferDsymbolSemantic(ed, scx);
2351 1
                    Module.dprogress = dprogress_save;
2352
                    //printf("\tdeferring %s\n", toChars());
2353 1
                    ed.semanticRun = PASS.init;
2354 1
                    return;
2355
                }
2356
            }
2357 1
            if (ed.memtype.ty == Tvoid)
2358
            {
2359 1
                ed.error("base type must not be `void`");
2360 1
                ed.memtype = Type.terror;
2361
            }
2362 1
            if (ed.memtype.ty == Terror)
2363
            {
2364 1
                ed.errors = true;
2365
                // poison all the members
2366 1
                ed.members.foreachDsymbol( (s) { s.errors = true; } );
2367 1
                ed.semanticRun = PASS.semanticdone;
2368 1
                return;
2369
            }
2370
        }
2371

2372 1
        ed.semanticRun = PASS.semanticdone;
2373

2374 1
        if (!ed.members) // enum ident : memtype;
2375 1
            return;
2376

2377 1
        if (ed.members.dim == 0)
2378
        {
2379 0
            ed.error("enum `%s` must have at least one member", ed.toChars());
2380 0
            ed.errors = true;
2381 0
            return;
2382
        }
2383

2384 1
        Module.dprogress++;
2385

2386 1
        Scope* sce;
2387 1
        if (ed.isAnonymous())
2388 1
            sce = sc;
2389
        else
2390
        {
2391 1
            sce = sc.push(ed);
2392 1
            sce.parent = ed;
2393
        }
2394 1
        sce = sce.startCTFE();
2395 1
        sce.setNoFree(); // needed for getMaxMinValue()
2396

2397
        /* Each enum member gets the sce scope
2398
         */
2399 1
        ed.members.foreachDsymbol( (s)
2400
        {
2401 1
            EnumMember em = s.isEnumMember();
2402 1
            if (em)
2403 1
                em._scope = sce;
2404
        });
2405

2406 1
        if (!ed.added)
2407
        {
2408
            /* addMember() is not called when the EnumDeclaration appears as a function statement,
2409
             * so we have to do what addMember() does and install the enum members in the right symbol
2410
             * table
2411
             */
2412 1
            ScopeDsymbol scopesym = null;
2413 1
            if (ed.isAnonymous())
2414
            {
2415
                /* Anonymous enum members get added to enclosing scope.
2416
                 */
2417 1
                for (Scope* sct = sce; 1; sct = sct.enclosing)
2418
                {
2419 1
                    assert(sct);
2420 1
                    if (sct.scopesym)
2421
                    {
2422 1
                        scopesym = sct.scopesym;
2423 1
                        if (!sct.scopesym.symtab)
2424 1
                            sct.scopesym.symtab = new DsymbolTable();
2425 1
                        break;
2426
                    }
2427
                }
2428
            }
2429
            else
2430
            {
2431
                // Otherwise enum members are in the EnumDeclaration's symbol table
2432 1
                scopesym = ed;
2433
            }
2434

2435 1
            ed.members.foreachDsymbol( (s)
2436
            {
2437 1
                EnumMember em = s.isEnumMember();
2438 1
                if (em)
2439
                {
2440 1
                    em.ed = ed;
2441 1
                    em.addMember(sc, scopesym);
2442
                }
2443
            });
2444
        }
2445

2446 1
        ed.members.foreachDsymbol( (s)
2447
        {
2448 1
            EnumMember em = s.isEnumMember();
2449 1
            if (em)
2450 1
                em.dsymbolSemantic(em._scope);
2451
        });
2452
        //printf("defaultval = %lld\n", defaultval);
2453

2454
        //if (defaultval) printf("defaultval: %s %s\n", defaultval.toChars(), defaultval.type.toChars());
2455
        //printf("members = %s\n", members.toChars());
2456
    }
2457

2458
    override void visit(EnumMember em)
2459
    {
2460
        //printf("EnumMember::semantic() %s\n", toChars());
2461

2462
        void errorReturn()
2463
        {
2464 1
            em.errors = true;
2465 1
            em.semanticRun = PASS.semanticdone;
2466
        }
2467

2468 1
        if (em.errors || em.semanticRun >= PASS.semanticdone)
2469 1
            return;
2470 1
        if (em.semanticRun == PASS.semantic)
2471
        {
2472 1
            em.error("circular reference to `enum` member");
2473 1
            return errorReturn();
2474
        }
2475 1
        assert(em.ed);
2476

2477 1
        em.ed.dsymbolSemantic(sc);
2478 1
        if (em.ed.errors)
2479 1
            return errorReturn();
2480 1
        if (em.errors || em.semanticRun >= PASS.semanticdone)
2481 1
            return;
2482

2483 1
        if (em._scope)
2484 1
            sc = em._scope;
2485 1
        if (!sc)
2486 0
            return;
2487

2488 1
        em.semanticRun = PASS.semantic;
2489

2490 1
        em.protection = em.ed.isAnonymous() ? em.ed.protection : Prot(Prot.Kind.public_);
2491 1
        em.linkage = LINK.d;
2492 1
        em.storage_class |= STC.manifest;
2493

2494
        // https://issues.dlang.org/show_bug.cgi?id=9701
2495 1
        if (em.ed.isAnonymous())
2496
        {
2497 1
            if (em.userAttribDecl)
2498 1
                em.userAttribDecl.userAttribDecl = em.ed.userAttribDecl;
2499
            else
2500 1
                em.userAttribDecl = em.ed.userAttribDecl;
2501
        }
2502

2503
        // Eval UDA in this same scope. Issues 19344, 20835, 21122
2504 1
        if (em.userAttribDecl)
2505 1
            em.userAttribDecl.setScope(sc);
2506

2507
        // The first enum member is special
2508 1
        bool first = (em == (*em.ed.members)[0]);
2509

2510 1
        if (em.origType)
2511
        {
2512 1
            em.origType = em.origType.typeSemantic(em.loc, sc);
2513 1
            em.type = em.origType;
2514 1
            assert(em.value); // "type id;" is not a valid enum member declaration
2515
        }
2516

2517 1
        if (em.value)
2518
        {
2519 1
            Expression e = em.value;
2520 1
            assert(e.dyncast() == DYNCAST.expression);
2521 1
            e = e.expressionSemantic(sc);
2522 1
            e = resolveProperties(sc, e);
2523 1
            e = e.ctfeInterpret();
2524 1
            if (e.op == TOK.error)
2525 1
                return errorReturn();
2526 1
            if (first && !em.ed.memtype && !em.ed.isAnonymous())
2527
            {
2528 1
                em.ed.memtype = e.type;
2529 1
                if (em.ed.memtype.ty == Terror)
2530
                {
2531 0
                    em.ed.errors = true;
2532 0
                    return errorReturn();
2533
                }
2534 1
                if (em.ed.memtype.ty != Terror)
2535
                {
2536
                    /* https://issues.dlang.org/show_bug.cgi?id=11746
2537
                     * All of named enum members should have same type
2538
                     * with the first member. If the following members were referenced
2539
                     * during the first member semantic, their types should be unified.
2540
                     */
2541 1
                    em.ed.members.foreachDsymbol( (s)
2542
                    {
2543 1
                        EnumMember enm = s.isEnumMember();
2544 1
                        if (!enm || enm == em || enm.semanticRun < PASS.semanticdone || enm.origType)
2545 1
                            return;
2546

2547
                        //printf("[%d] em = %s, em.semanticRun = %d\n", i, toChars(), em.semanticRun);
2548 1
                        Expression ev = enm.value;
2549 1
                        ev = ev.implicitCastTo(sc, em.ed.memtype);
2550 1
                        ev = ev.ctfeInterpret();
2551 1
                        ev = ev.castTo(sc, em.ed.type);
2552 1
                        if (ev.op == TOK.error)
2553 1
                            em.ed.errors = true;
2554 1
                        enm.value = ev;
2555
                    });
2556

2557 1
                    if (em.ed.errors)
2558
                    {
2559 1
                        em.ed.memtype = Type.terror;
2560 1
                        return errorReturn();
2561
                    }
2562
                }
2563
            }
2564

2565 1
            if (em.ed.memtype && !em.origType)
2566
            {
2567 1
                e = e.implicitCastTo(sc, em.ed.memtype);
2568 1
                e = e.ctfeInterpret();
2569

2570
                // save origValue for better json output
2571 1
                em.origValue = e;
2572

2573 1
                if (!em.ed.isAnonymous())
2574
                {
2575 1
                    e = e.castTo(sc, em.ed.type.addMod(e.type.mod)); // https://issues.dlang.org/show_bug.cgi?id=12385
2576 1
                    e = e.ctfeInterpret();
2577
                }
2578
            }
2579 1
            else if (em.origType)
2580
            {
2581 1
                e = e.implicitCastTo(sc, em.origType);
2582 1
                e = e.ctfeInterpret();
2583 1
                assert(em.ed.isAnonymous());
2584

2585
                // save origValue for better json output
2586 1
                em.origValue = e;
2587
            }
2588 1
            em.value = e;
2589
        }
2590 1
        else if (first)
2591
        {
2592 1
            Type t;
2593 1
            if (em.ed.memtype)
2594 1
                t = em.ed.memtype;
2595
            else
2596
            {
2597 1
                t = Type.tint32;
2598 1
                if (!em.ed.isAnonymous())
2599 1
                    em.ed.memtype = t;
2600
            }
2601 1
            Expression e = new IntegerExp(em.loc, 0, t);
2602 1
            e = e.ctfeInterpret();
2603

2604
            // save origValue for better json output
2605 1
            em.origValue = e;
2606

2607 1
            if (!em.ed.isAnonymous())
2608
            {
2609 1
                e = e.castTo(sc, em.ed.type);
2610 1
                e = e.ctfeInterpret();
2611
            }
2612 1
            em.value = e;
2613
        }
2614
        else
2615
        {
2616
            /* Find the previous enum member,
2617
             * and set this to be the previous value + 1
2618
             */
2619 1
            EnumMember emprev = null;
2620 1
            em.ed.members.foreachDsymbol( (s)
2621
            {
2622 1
                if (auto enm = s.isEnumMember())
2623
                {
2624 1
                    if (enm == em)
2625 1
                        return 1;       // found
2626 1
                    emprev = enm;
2627
                }
2628 1
                return 0;       // continue
2629
            });
2630

2631 1
            assert(emprev);
2632 1
            if (emprev.semanticRun < PASS.semanticdone) // if forward reference
2633 1
                emprev.dsymbolSemantic(emprev._scope); // resolve it
2634 1
            if (emprev.errors)
2635 1
                return errorReturn();
2636

2637 1
            Expression eprev = emprev.value;
2638
            // .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645
2639 1
            Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
2640 1
                ? em.ed.memtype
2641 1
                : eprev.type;
2642

2643 1
            Expression emax = tprev.getProperty(sc, em.ed.loc, Id.max, 0);
2644 1
            emax = emax.expressionSemantic(sc);
2645 1
            emax = emax.ctfeInterpret();
2646

2647
            // Set value to (eprev + 1).
2648
            // But first check that (eprev != emax)
2649 1
            assert(eprev);
2650 1
            Expression e = new EqualExp(TOK.equal, em.loc, eprev, emax);
2651 1
            e = e.expressionSemantic(sc);
2652 1
            e = e.ctfeInterpret();
2653 1
            if (e.toInteger())
2654
            {
2655 1
                em.error("initialization with `%s.%s+1` causes overflow for type `%s`",
2656
                    emprev.ed.toChars(), emprev.toChars(), em.ed.memtype.toChars());
2657 1
                return errorReturn();
2658
            }
2659

2660
            // Now set e to (eprev + 1)
2661 1
            e = new AddExp(em.loc, eprev, IntegerExp.literal!1);
2662 1
            e = e.expressionSemantic(sc);
2663 1
            e = e.castTo(sc, eprev.type);
2664 1
            e = e.ctfeInterpret();
2665

2666
            // save origValue (without cast) for better json output
2667 1
            if (e.op != TOK.error) // avoid duplicate diagnostics
2668
            {
2669 1
                assert(emprev.origValue);
2670 1
                em.origValue = new AddExp(em.loc, emprev.origValue, IntegerExp.literal!1);
2671 1
                em.origValue = em.origValue.expressionSemantic(sc);
2672 1
                em.origValue = em.origValue.ctfeInterpret();
2673
            }
2674

2675 1
            if (e.op == TOK.error)
2676 1
                return errorReturn();
2677 1
            if (e.type.isfloating())
2678
            {
2679
                // Check that e != eprev (not always true for floats)
2680 1
                Expression etest = new EqualExp(TOK.equal, em.loc, e, eprev);
2681 1
                etest = etest.expressionSemantic(sc);
2682 1
                etest = etest.ctfeInterpret();
2683 1
                if (etest.toInteger())
2684
                {
2685 1
                    em.error("has inexact value due to loss of precision");
2686 1
                    return errorReturn();
2687
                }
2688
            }
2689 1
            em.value = e;
2690
        }
2691 1
        if (!em.origType)
2692 1
            em.type = em.value.type;
2693

2694 1
        assert(em.origValue);
2695 1
        em.semanticRun = PASS.semanticdone;
2696
    }
2697

2698
    override void visit(TemplateDeclaration tempdecl)
2699
    {
2700
        static if (LOG)
2701
        {
2702
            printf("TemplateDeclaration.dsymbolSemantic(this = %p, id = '%s')\n", this, tempdecl.ident.toChars());
2703
            printf("sc.stc = %llx\n", sc.stc);
2704
            printf("sc.module = %s\n", sc._module.toChars());
2705
        }
2706 1
        if (tempdecl.semanticRun != PASS.init)
2707 1
            return; // semantic() already run
2708

2709 1
        if (tempdecl._scope)
2710
        {
2711 1
            sc = tempdecl._scope;
2712 1
            tempdecl._scope = null;
2713
        }
2714 1
        if (!sc)
2715 0
            return;
2716

2717
        // Remember templates defined in module object that we need to know about
2718 1
        if (sc._module && sc._module.ident == Id.object)
2719
        {
2720 1
            if (tempdecl</