1
/**
2
 * Semantic analysis of expressions.
3
 *
4
 * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
5
 *
6
 * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
7
 * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8
 * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d)
10
 * Documentation:  https://dlang.org/phobos/dmd_expressionsem.html
11
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expressionsem.d
12
 */
13

14
module dmd.expressionsem;
15

16
import core.stdc.stdio;
17

18
import dmd.access;
19
import dmd.aggregate;
20
import dmd.aliasthis;
21
import dmd.arrayop;
22
import dmd.arraytypes;
23
import dmd.attrib;
24
import dmd.astcodegen;
25
import dmd.canthrow;
26
import dmd.chkformat;
27
import dmd.ctorflow;
28
import dmd.dscope;
29
import dmd.dsymbol;
30
import dmd.declaration;
31
import dmd.dclass;
32
import dmd.dcast;
33
import dmd.delegatize;
34
import dmd.denum;
35
import dmd.dimport;
36
import dmd.dinterpret;
37
import dmd.dmangle;
38
import dmd.dmodule;
39
import dmd.dstruct;
40
import dmd.dsymbolsem;
41
import dmd.dtemplate;
42
import dmd.errors;
43
import dmd.escape;
44
import dmd.expression;
45
import dmd.func;
46
import dmd.globals;
47
import dmd.hdrgen;
48
import dmd.id;
49
import dmd.identifier;
50
import dmd.imphint;
51
import dmd.init;
52
import dmd.initsem;
53
import dmd.inline;
54
import dmd.intrange;
55
import dmd.mtype;
56
import dmd.nspace;
57
import dmd.opover;
58
import dmd.optimize;
59
import dmd.parse;
60
import dmd.root.ctfloat;
61
import dmd.root.file;
62
import dmd.root.filename;
63
import dmd.root.outbuffer;
64
import dmd.root.rmem;
65
import dmd.root.rootobject;
66
import dmd.root.string;
67
import dmd.semantic2;
68
import dmd.semantic3;
69
import dmd.sideeffect;
70
import dmd.safe;
71
import dmd.target;
72
import dmd.tokens;
73
import dmd.traits;
74
import dmd.typesem;
75
import dmd.typinf;
76
import dmd.utf;
77
import dmd.utils;
78
import dmd.visitor;
79

80
enum LOGSEMANTIC = false;
81

82
/********************************************************
83
 * Perform semantic analysis and CTFE on expressions to produce
84
 * a string.
85
 * Params:
86
 *      buf = append generated string to buffer
87
 *      sc = context
88
 *      exps = array of Expressions
89
 * Returns:
90
 *      true on error
91
 */
92
bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
93
{
94 1
    if (!exps)
95 0
        return false;
96

97 1
    foreach (ex; *exps)
98
    {
99 1
        if (!ex)
100 0
            continue;
101 1
        auto sc2 = sc.startCTFE();
102 1
        auto e2 = ex.expressionSemantic(sc2);
103 1
        auto e3 = resolveProperties(sc2, e2);
104 1
        sc2.endCTFE();
105

106
        // allowed to contain types as well as expressions
107 1
        auto e4 = ctfeInterpretForPragmaMsg(e3);
108 1
        if (!e4 || e4.op == TOK.error)
109 1
            return true;
110

111
        // expand tuple
112 1
        if (auto te = e4.isTupleExp())
113
        {
114 1
            if (expressionsToString(buf, sc, te.exps))
115 0
                return true;
116 1
            continue;
117
        }
118
        // char literals exp `.toStringExp` return `null` but we cant override it
119
        // because in most contexts we don't want the conversion to succeed.
120 1
        IntegerExp ie = e4.isIntegerExp();
121 1
        const ty = (ie && ie.type) ? ie.type.ty : Terror;
122 1
        if (ty.isSomeChar)
123
        {
124 1
            auto tsa = new TypeSArray(ie.type, IntegerExp.literal!1);
125 1
            e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
126
        }
127

128 1
        if (StringExp se = e4.toStringExp())
129 1
            buf.writestring(se.toUTF8(sc).peekString());
130
        else
131 1
            buf.writestring(e4.toString());
132
    }
133 1
    return false;
134
}
135

136

137
/***********************************************************
138
 * Resolve `exp` as a compile-time known string.
139
 * Params:
140
 *  sc  = scope
141
 *  exp = Expression which expected as a string
142
 *  s   = What the string is expected for, will be used in error diagnostic.
143
 * Returns:
144
 *  String literal, or `null` if error happens.
145
 */
146
StringExp semanticString(Scope *sc, Expression exp, const char* s)
147
{
148 1
    sc = sc.startCTFE();
149 1
    exp = exp.expressionSemantic(sc);
150 1
    exp = resolveProperties(sc, exp);
151 1
    sc = sc.endCTFE();
152

153 1
    if (exp.op == TOK.error)
154 1
        return null;
155

156 1
    auto e = exp;
157 1
    if (exp.type.isString())
158
    {
159 1
        e = e.ctfeInterpret();
160 1
        if (e.op == TOK.error)
161 0
            return null;
162
    }
163

164 1
    auto se = e.toStringExp();
165 1
    if (!se)
166
    {
167 1
        exp.error("`string` expected for %s, not `(%s)` of type `%s`",
168
            s, exp.toChars(), exp.type.toChars());
169 1
        return null;
170
    }
171 1
    return se;
172
}
173

174
private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
175
{
176 1
    Expression e0;
177 1
    Expression e1 = Expression.extractLast(ue.e1, e0);
178
    // https://issues.dlang.org/show_bug.cgi?id=12585
179
    // Extract the side effect part if ue.e1 is comma.
180

181 1
    if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect()
182
    {
183
        /* Even if opDollar is needed, 'e1' should be evaluate only once. So
184
         * Rewrite:
185
         *      e1.opIndex( ... use of $ ... )
186
         *      e1.opSlice( ... use of $ ... )
187
         * as:
188
         *      (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
189
         *      (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
190
         */
191 1
        e1 = extractSideEffect(sc, "__dop", e0, e1, false);
192 1
        assert(e1.op == TOK.variable);
193 1
        VarExp ve = cast(VarExp)e1;
194 1
        ve.var.storage_class |= STC.exptemp;     // lifetime limited to expression
195
    }
196 1
    ue.e1 = e1;
197 1
    return e0;
198
}
199

200
/**************************************
201
 * Runs semantic on ae.arguments. Declares temporary variables
202
 * if '$' was used.
203
 */
204
Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
205
{
206 1
    assert(!ae.lengthVar);
207 1
    *pe0 = null;
208 1
    AggregateDeclaration ad = isAggregate(ae.e1.type);
209 1
    Dsymbol slice = search_function(ad, Id.slice);
210
    //printf("slice = %s %s\n", slice.kind(), slice.toChars());
211 1
    foreach (i, e; *ae.arguments)
212
    {
213 1
        if (i == 0)
214 1
            *pe0 = extractOpDollarSideEffect(sc, ae);
215

216 1
        if (e.op == TOK.interval && !(slice && slice.isTemplateDeclaration()))
217
        {
218
        Lfallback:
219 1
            if (ae.arguments.dim == 1)
220 1
                return null;
221 1
            ae.error("multi-dimensional slicing requires template `opSlice`");
222 1
            return ErrorExp.get();
223
        }
224
        //printf("[%d] e = %s\n", i, e.toChars());
225

226
        // Create scope for '$' variable for this dimension
227 1
        auto sym = new ArrayScopeSymbol(sc, ae);
228 1
        sym.parent = sc.scopesym;
229 1
        sc = sc.push(sym);
230 1
        ae.lengthVar = null; // Create it only if required
231 1
        ae.currentDimension = i; // Dimension for $, if required
232

233 1
        e = e.expressionSemantic(sc);
234 1
        e = resolveProperties(sc, e);
235

236 1
        if (ae.lengthVar && sc.func)
237
        {
238
            // If $ was used, declare it now
239 1
            Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
240 1
            de = de.expressionSemantic(sc);
241 1
            *pe0 = Expression.combine(*pe0, de);
242
        }
243 1
        sc = sc.pop();
244

245 1
        if (e.op == TOK.interval)
246
        {
247 1
            IntervalExp ie = cast(IntervalExp)e;
248

249 1
            auto tiargs = new Objects();
250 1
            Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
251 1
            edim = edim.expressionSemantic(sc);
252 1
            tiargs.push(edim);
253

254 1
            auto fargs = new Expressions(2);
255 1
            (*fargs)[0] = ie.lwr;
256 1
            (*fargs)[1] = ie.upr;
257

258 1
            uint xerrors = global.startGagging();
259 1
            sc = sc.push();
260 1
            FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet);
261 1
            sc = sc.pop();
262 1
            global.endGagging(xerrors);
263 1
            if (!fslice)
264 1
                goto Lfallback;
265

266 1
            e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
267 1
            e = new CallExp(ae.loc, e, fargs);
268 1
            e = e.expressionSemantic(sc);
269
        }
270

271 1
        if (!e.type)
272
        {
273 0
            ae.error("`%s` has no value", e.toChars());
274 0
            e = ErrorExp.get();
275
        }
276 1
        if (e.op == TOK.error)
277 1
            return e;
278

279 1
        (*ae.arguments)[i] = e;
280
    }
281 1
    return ae;
282
}
283

284
/**************************************
285
 * Runs semantic on se.lwr and se.upr. Declares a temporary variable
286
 * if '$' was used.
287
 * Returns:
288
 *      ae, or ErrorExp if errors occurred
289
 */
290
Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
291
{
292
    //assert(!ae.lengthVar);
293 1
    if (!ie)
294 1
        return ae;
295

296 1
    VarDeclaration lengthVar = ae.lengthVar;
297 1
    bool errors = false;
298

299
    // create scope for '$'
300 1
    auto sym = new ArrayScopeSymbol(sc, ae);
301 1
    sym.parent = sc.scopesym;
302 1
    sc = sc.push(sym);
303

304
    Expression sem(Expression e)
305
    {
306 1
        e = e.expressionSemantic(sc);
307 1
        e = resolveProperties(sc, e);
308 1
        if (!e.type)
309
        {
310 0
            ae.error("`%s` has no value", e.toChars());
311 0
            errors = true;
312
        }
313 1
        return e;
314
    }
315

316 1
    ie.lwr = sem(ie.lwr);
317 1
    ie.upr = sem(ie.upr);
318

319 1
    if (lengthVar != ae.lengthVar && sc.func)
320
    {
321
        // If $ was used, declare it now
322 1
        Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
323 1
        de = de.expressionSemantic(sc);
324 1
        *pe0 = Expression.combine(*pe0, de);
325
    }
326

327 1
    sc = sc.pop();
328

329 1
    return errors ? ErrorExp.get() : ae;
330
}
331

332
/******************************
333
 * Perform semantic() on an array of Expressions.
334
 */
335
bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
336
{
337 1
    bool err = false;
338 1
    if (exps)
339
    {
340 1
        foreach (ref e; *exps)
341
        {
342 1
            if (e)
343
            {
344 1
                auto e2 = e.expressionSemantic(sc);
345 1
                if (e2.op == TOK.error)
346 1
                    err = true;
347 1
                if (preserveErrors || e2.op != TOK.error)
348 1
                    e = e2;
349
            }
350
        }
351
    }
352 1
    return err;
353
}
354

355
/******************************
356
 * Check the tail CallExp is really property function call.
357
 * Bugs:
358
 * This doesn't appear to do anything.
359
 */
360
private bool checkPropertyCall(Expression e)
361
{
362 1
    e = lastComma(e);
363

364 1
    if (e.op == TOK.call)
365
    {
366 1
        CallExp ce = cast(CallExp)e;
367 1
        TypeFunction tf;
368 1
        if (ce.f)
369
        {
370 1
            tf = cast(TypeFunction)ce.f.type;
371
            /* If a forward reference to ce.f, try to resolve it
372
             */
373 1
            if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
374
            {
375 0
                ce.f.dsymbolSemantic(null);
376 0
                tf = cast(TypeFunction)ce.f.type;
377
            }
378
        }
379 0
        else if (ce.e1.type.ty == Tfunction)
380 0
            tf = cast(TypeFunction)ce.e1.type;
381 0
        else if (ce.e1.type.ty == Tdelegate)
382 0
            tf = cast(TypeFunction)ce.e1.type.nextOf();
383 0
        else if (ce.e1.type.ty == Tpointer && ce.e1.type.nextOf().ty == Tfunction)
384 0
            tf = cast(TypeFunction)ce.e1.type.nextOf();
385
        else
386 0
            assert(0);
387
    }
388 1
    return false;
389
}
390

391
/******************************
392
 * Find symbol in accordance with the UFCS name look up rule
393
 */
394
private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
395
{
396
    //printf("searchUFCS(ident = %s)\n", ident.toChars());
397 1
    Loc loc = ue.loc;
398

399
    // TODO: merge with Scope.search.searchScopes()
400
    Dsymbol searchScopes(int flags)
401
    {
402 1
        Dsymbol s = null;
403 1
        for (Scope* scx = sc; scx; scx = scx.enclosing)
404
        {
405 1
            if (!scx.scopesym)
406 1
                continue;
407 1
            if (scx.scopesym.isModule())
408 1
                flags |= SearchUnqualifiedModule;    // tell Module.search() that SearchLocalsOnly is to be obeyed
409 1
            s = scx.scopesym.search(loc, ident, flags);
410 1
            if (s)
411
            {
412
                // overload set contains only module scope symbols.
413 1
                if (s.isOverloadSet())
414 1
                    break;
415
                // selective/renamed imports also be picked up
416 1
                if (AliasDeclaration ad = s.isAliasDeclaration())
417
                {
418 1
                    if (ad._import)
419 1
                        break;
420
                }
421
                // See only module scope symbols for UFCS target.
422 1
                Dsymbol p = s.toParent2();
423 1
                if (p && p.isModule())
424 1
                    break;
425
            }
426 1
            s = null;
427

428
            // Stop when we hit a module, but keep going if that is not just under the global scope
429 1
            if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
430 0
                break;
431
        }
432 1
        return s;
433
    }
434

435 1
    int flags = 0;
436 1
    Dsymbol s;
437

438 1
    if (sc.flags & SCOPE.ignoresymbolvisibility)
439 1
        flags |= IgnoreSymbolVisibility;
440

441
    // First look in local scopes
442 1
    s = searchScopes(flags | SearchLocalsOnly);
443 1
    if (!s)
444
    {
445
        // Second look in imported modules
446 1
        s = searchScopes(flags | SearchImportsOnly);
447
    }
448

449 1
    if (!s)
450 1
        return ue.e1.type.Type.getProperty(sc, loc, ident, 0);
451

452 1
    FuncDeclaration f = s.isFuncDeclaration();
453 1
    if (f)
454
    {
455 1
        TemplateDeclaration td = getFuncTemplateDecl(f);
456 1
        if (td)
457
        {
458 1
            if (td.overroot)
459 1
                td = td.overroot;
460 1
            s = td;
461
        }
462
    }
463

464 1
    if (ue.op == TOK.dotTemplateInstance)
465
    {
466 1
        DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ue;
467 1
        auto ti = Pool!TemplateInstance.make(loc, s.ident, dti.ti.tiargs);
468 1
        if (!ti.updateTempDecl(sc, s))
469 1
            return ErrorExp.get();
470 1
        return new ScopeExp(loc, ti);
471
    }
472
    else
473
    {
474
        //printf("-searchUFCS() %s\n", s.toChars());
475 1
        return new DsymbolExp(loc, s);
476
    }
477
}
478

479
/******************************
480
 * Pull out callable entity with UFCS.
481
 */
482
private Expression resolveUFCS(Scope* sc, CallExp ce)
483
{
484 1
    Loc loc = ce.loc;
485 1
    Expression eleft;
486 1
    Expression e;
487

488 1
    if (ce.e1.op == TOK.dotIdentifier)
489
    {
490 1
        DotIdExp die = cast(DotIdExp)ce.e1;
491 1
        Identifier ident = die.ident;
492

493 1
        Expression ex = die.semanticX(sc);
494 1
        if (ex != die)
495
        {
496 1
            ce.e1 = ex;
497 1
            return null;
498
        }
499 1
        eleft = die.e1;
500

501 1
        Type t = eleft.type.toBasetype();
502 1
        if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
503
        {
504
            /* Built-in types and arrays have no callable properties, so do shortcut.
505
             * It is necessary in: e.init()
506
             */
507
        }
508 1
        else if (t.ty == Taarray)
509
        {
510 1
            if (ident == Id.remove)
511
            {
512
                /* Transform:
513
                 *  aa.remove(arg) into delete aa[arg]
514
                 */
515 1
                if (!ce.arguments || ce.arguments.dim != 1)
516
                {
517 0
                    ce.error("expected key as argument to `aa.remove()`");
518 0
                    return ErrorExp.get();
519
                }
520 1
                if (!eleft.type.isMutable())
521
                {
522 1
                    ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
523 1
                    return ErrorExp.get();
524
                }
525 1
                Expression key = (*ce.arguments)[0];
526 1
                key = key.expressionSemantic(sc);
527 1
                key = resolveProperties(sc, key);
528

529 1
                TypeAArray taa = cast(TypeAArray)t;
530 1
                key = key.implicitCastTo(sc, taa.index);
531

532 1
                if (key.checkValue() || key.checkSharedAccess(sc))
533 0
                    return ErrorExp.get();
534

535 1
                semanticTypeInfo(sc, taa.index);
536

537 1
                return new RemoveExp(loc, eleft, key);
538
            }
539
        }
540
        else
541
        {
542 1
            if (Expression ey = die.semanticY(sc, 1))
543
            {
544 1
                if (ey.op == TOK.error)
545 1
                    return ey;
546 1
                ce.e1 = ey;
547 1
                if (isDotOpDispatch(ey))
548
                {
549 1
                    uint errors = global.startGagging();
550 1
                    e = ce.syntaxCopy().expressionSemantic(sc);
551 1
                    if (!global.endGagging(errors))
552 1
                        return e;
553

554
                    // even opDispatch and UFCS must have valid arguments,
555
                    // so now that we've seen indication of a problem,
556
                    // check them for issues.
557 1
                    Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
558

559 1
                    if (arrayExpressionSemantic(originalArguments, sc))
560 1
                        return ErrorExp.get();
561

562
                    /* fall down to UFCS */
563
                }
564
                else
565 1
                    return null;
566
            }
567
        }
568

569
        /* https://issues.dlang.org/show_bug.cgi?id=13953
570
         *
571
         * If a struct has an alias this to an associative array
572
         * and remove is used on a struct instance, we have to
573
         * check first if there is a remove function that can be called
574
         * on the struct. If not we must check the alias this.
575
         *
576
         * struct A
577
         * {
578
         *      string[string] a;
579
         *      alias a this;
580
         * }
581
         *
582
         * void fun()
583
         * {
584
         *      A s;
585
         *      s.remove("foo");
586
         * }
587
         */
588 1
        const errors = global.startGagging();
589 1
        e = searchUFCS(sc, die, ident);
590
        // if there were any errors and the identifier was remove
591 1
        if (global.endGagging(errors))
592
        {
593 1
            if (ident == Id.remove)
594
            {
595
                // check alias this
596 1
                Expression alias_e = resolveAliasThis(sc, die.e1, 1);
597 1
                if (alias_e && alias_e != die.e1)
598
                {
599 1
                    die.e1 = alias_e;
600 1
                    CallExp ce2 = cast(CallExp)ce.syntaxCopy();
601 1
                    ce2.e1 = die;
602 1
                    e = cast(CallExp)ce2.trySemantic(sc);
603 1
                    if (e)
604 1
                        return e;
605
                }
606
            }
607
            // if alias this did not work out, print the initial errors
608 1
            searchUFCS(sc, die, ident);
609
        }
610
    }
611 1
    else if (ce.e1.op == TOK.dotTemplateInstance)
612
    {
613 1
        DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ce.e1;
614 1
        if (Expression ey = dti.semanticY(sc, 1))
615
        {
616 1
            ce.e1 = ey;
617 1
            return null;
618
        }
619 1
        eleft = dti.e1;
620 1
        e = searchUFCS(sc, dti, dti.ti.name);
621
    }
622
    else
623 1
        return null;
624

625
    // Rewrite
626 1
    ce.e1 = e;
627 1
    if (!ce.arguments)
628 0
        ce.arguments = new Expressions();
629 1
    ce.arguments.shift(eleft);
630

631 1
    return null;
632
}
633

634
/******************************
635
 * Pull out property with UFCS.
636
 */
637
private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
638
{
639 1
    Loc loc = e1.loc;
640 1
    Expression eleft;
641 1
    Expression e;
642

643 1
    if (e1.op == TOK.dotIdentifier)
644
    {
645 1
        DotIdExp die = cast(DotIdExp)e1;
646 1
        eleft = die.e1;
647 1
        e = searchUFCS(sc, die, die.ident);
648
    }
649 1
    else if (e1.op == TOK.dotTemplateInstance)
650
    {
651 1
        DotTemplateInstanceExp dti;
652 1
        dti = cast(DotTemplateInstanceExp)e1;
653 1
        eleft = dti.e1;
654 1
        e = searchUFCS(sc, dti, dti.ti.name);
655
    }
656
    else
657 0
        return null;
658

659 1
    if (e is null)
660 1
        return null;
661

662
    // Rewrite
663 1
    if (e2)
664
    {
665
        // run semantic without gagging
666 1
        e2 = e2.expressionSemantic(sc);
667

668
        /* f(e1) = e2
669
         */
670 1
        Expression ex = e.copy();
671 1
        auto a1 = new Expressions(1);
672 1
        (*a1)[0] = eleft;
673 1
        ex = new CallExp(loc, ex, a1);
674 1
        auto e1PassSemantic = ex.trySemantic(sc);
675

676
        /* f(e1, e2)
677
         */
678 1
        auto a2 = new Expressions(2);
679 1
        (*a2)[0] = eleft;
680 1
        (*a2)[1] = e2;
681 1
        e = new CallExp(loc, e, a2);
682 1
        e = e.trySemantic(sc);
683 1
        if (!e1PassSemantic && !e)
684
        {
685
            /* https://issues.dlang.org/show_bug.cgi?id=20448
686
             *
687
             * If both versions have failed to pass semantic,
688
             * f(e1) = e2 gets priority in error printing
689
             * because f might be a templated function that
690
             * failed to instantiate and we have to print
691
             * the instantiation errors.
692
             */
693 1
            return e1.expressionSemantic(sc);
694
        }
695 1
        else if (ex && !e)
696
        {
697 1
            checkPropertyCall(ex);
698 1
            ex = new AssignExp(loc, ex, e2);
699 1
            return ex.expressionSemantic(sc);
700
        }
701
        else
702
        {
703
            // strict setter prints errors if fails
704 1
            e = e.expressionSemantic(sc);
705
        }
706 1
        checkPropertyCall(e);
707 1
        return e;
708
    }
709
    else
710
    {
711
        /* f(e1)
712
         */
713 1
        auto arguments = new Expressions(1);
714 1
        (*arguments)[0] = eleft;
715 1
        e = new CallExp(loc, e, arguments);
716 1
        e = e.expressionSemantic(sc);
717 1
        checkPropertyCall(e);
718 1
        return e.expressionSemantic(sc);
719
    }
720
}
721

722
/******************************
723
 * If e1 is a property function (template), resolve it.
724
 */
725
Expression resolvePropertiesOnly(Scope* sc, Expression e1)
726
{
727
    //printf("e1 = %s %s\n", Token::toChars(e1.op), e1.toChars());
728

729
    Expression handleOverloadSet(OverloadSet os)
730
    {
731 0
        assert(os);
732 0
        foreach (s; os.a)
733
        {
734 0
            auto fd = s.isFuncDeclaration();
735 0
            auto td = s.isTemplateDeclaration();
736 0
            if (fd)
737
            {
738 0
                if ((cast(TypeFunction)fd.type).isproperty)
739 0
                    return resolveProperties(sc, e1);
740
            }
741 0
            else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
742
            {
743 0
                if ((cast(TypeFunction)fd.type).isproperty ||
744 0
                    (fd.storage_class2 & STC.property) ||
745 0
                    (td._scope.stc & STC.property))
746 0
                    return resolveProperties(sc, e1);
747
            }
748
        }
749 0
        return e1;
750
    }
751

752
    Expression handleTemplateDecl(TemplateDeclaration td)
753
    {
754 1
        assert(td);
755 1
        if (td.onemember)
756
        {
757 1
            if (auto fd = td.onemember.isFuncDeclaration())
758
            {
759 1
                if ((cast(TypeFunction)fd.type).isproperty ||
760 1
                    (fd.storage_class2 & STC.property) ||
761 1
                    (td._scope.stc & STC.property))
762 1
                    return resolveProperties(sc, e1);
763
            }
764
        }
765 1
        return e1;
766
    }
767

768
    Expression handleFuncDecl(FuncDeclaration fd)
769
    {
770 1
        assert(fd);
771 1
        if ((cast(TypeFunction)fd.type).isproperty)
772 1
            return resolveProperties(sc, e1);
773 1
        return e1;
774
    }
775

776 1
    if (auto de = e1.isDotExp())
777
    {
778 0
        if (auto os = de.e2.isOverExp())
779 0
            return handleOverloadSet(os.vars);
780
    }
781 1
    else if (auto oe = e1.isOverExp())
782 0
        return handleOverloadSet(oe.vars);
783 1
    else if (auto dti = e1.isDotTemplateInstanceExp())
784
    {
785 1
        if (dti.ti.tempdecl)
786 1
            if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
787 1
                return handleTemplateDecl(td);
788
    }
789 1
    else if (auto dte = e1.isDotTemplateExp())
790 1
        return handleTemplateDecl(dte.td);
791 1
    else if (e1.op == TOK.scope_)
792
    {
793 1
        Dsymbol s = (cast(ScopeExp)e1).sds;
794 1
        TemplateInstance ti = s.isTemplateInstance();
795 1
        if (ti && !ti.semanticRun && ti.tempdecl)
796 1
            if (auto td = ti.tempdecl.isTemplateDeclaration())
797 1
                return handleTemplateDecl(td);
798
    }
799 1
    else if (e1.op == TOK.template_)
800 1
        return handleTemplateDecl((cast(TemplateExp)e1).td);
801 1
    else if (e1.op == TOK.dotVariable && e1.type.ty == Tfunction)
802
    {
803 1
        DotVarExp dve = cast(DotVarExp)e1;
804 1
        return handleFuncDecl(dve.var.isFuncDeclaration());
805
    }
806 1
    else if (e1.op == TOK.variable && e1.type && e1.type.ty == Tfunction && (sc.intypeof || !(cast(VarExp)e1).var.needThis()))
807 1
        return handleFuncDecl((cast(VarExp)e1).var.isFuncDeclaration());
808 1
    return e1;
809
}
810

811
/****************************************
812
 * Turn symbol `s` into the expression it represents.
813
 *
814
 * Params:
815
 *      s = symbol to resolve
816
 *      loc = location of use of `s`
817
 *      sc = context
818
 *      hasOverloads = applies if `s` represents a function.
819
 *          true means it's overloaded and will be resolved later,
820
 *          false means it's the exact function symbol.
821
 * Returns:
822
 *      `s` turned into an expression, `ErrorExp` if an error occurred
823
 */
824
Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
825
{
826
    static if (LOGSEMANTIC)
827
    {
828
        printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
829
    }
830

831
Lagain:
832 1
    Expression e;
833

834
    //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
835
    //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
836 1
    Dsymbol olds = s;
837 1
    Declaration d = s.isDeclaration();
838 1
    if (d && (d.storage_class & STC.templateparameter))
839
    {
840 1
        s = s.toAlias();
841
    }
842
    else
843
    {
844 1
        if (!s.isFuncDeclaration()) // functions are checked after overloading
845
        {
846 1
            s.checkDeprecated(loc, sc);
847 1
            if (d)
848 1
                d.checkDisabled(loc, sc);
849
        }
850

851
        // https://issues.dlang.org/show_bug.cgi?id=12023
852
        // if 's' is a tuple variable, the tuple is returned.
853 1
        s = s.toAlias();
854

855
        //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
856 1
        if (s != olds && !s.isFuncDeclaration())
857
        {
858 1
            s.checkDeprecated(loc, sc);
859 1
            if (d)
860 1
                d.checkDisabled(loc, sc);
861
        }
862
    }
863

864 1
    if (auto em = s.isEnumMember())
865
    {
866 1
        return em.getVarExp(loc, sc);
867
    }
868 1
    if (auto v = s.isVarDeclaration())
869
    {
870
        //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
871 1
        if (sc.intypeof == 1 && !v.inuse)
872 1
            v.dsymbolSemantic(sc);
873 1
        if (!v.type ||                  // during variable type inference
874 1
            !v.type.deco && v.inuse)    // during variable type semantic
875
        {
876 1
            if (v.inuse)    // variable type depends on the variable itself
877 1
                error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
878
            else            // variable type cannot be determined
879 0
                error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
880 1
            return ErrorExp.get();
881
        }
882 1
        if (v.type.ty == Terror)
883 1
            return ErrorExp.get();
884

885 1
        if ((v.storage_class & STC.manifest) && v._init)
886
        {
887 1
            if (v.inuse)
888
            {
889 1
                error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
890 1
                return ErrorExp.get();
891
            }
892 1
            e = v.expandInitializer(loc);
893 1
            v.inuse++;
894 1
            e = e.expressionSemantic(sc);
895 1
            v.inuse--;
896 1
            return e;
897
        }
898

899
        // Change the ancestor lambdas to delegate before hasThis(sc) call.
900 1
        if (v.checkNestedReference(sc, loc))
901 1
            return ErrorExp.get();
902

903 1
        if (v.needThis() && hasThis(sc))
904 1
            e = new DotVarExp(loc, new ThisExp(loc), v);
905
        else
906 1
            e = new VarExp(loc, v);
907 1
        e = e.expressionSemantic(sc);
908 1
        return e;
909
    }
910 1
    if (auto fld = s.isFuncLiteralDeclaration())
911
    {
912
        //printf("'%s' is a function literal\n", fld.toChars());
913 1
        e = new FuncExp(loc, fld);
914 1
        return e.expressionSemantic(sc);
915
    }
916 1
    if (auto f = s.isFuncDeclaration())
917
    {
918 1
        f = f.toAliasFunc();
919 1
        if (!f.functionSemantic())
920 1
            return ErrorExp.get();
921

922 1
        if (!hasOverloads && f.checkForwardRef(loc))
923 0
            return ErrorExp.get();
924

925 1
        auto fd = s.isFuncDeclaration();
926 1
        fd.type = f.type;
927 1
        return new VarExp(loc, fd, hasOverloads);
928
    }
929 1
    if (OverDeclaration od = s.isOverDeclaration())
930
    {
931 1
        e = new VarExp(loc, od, true);
932 1
        e.type = Type.tvoid;
933 1
        return e;
934
    }
935 1
    if (OverloadSet o = s.isOverloadSet())
936
    {
937
        //printf("'%s' is an overload set\n", o.toChars());
938 1
        return new OverExp(loc, o);
939
    }
940

941 1
    if (Import imp = s.isImport())
942
    {
943 1
        if (!imp.pkg)
944
        {
945 0
            .error(loc, "forward reference of import `%s`", imp.toChars());
946 0
            return ErrorExp.get();
947
        }
948 1
        auto ie = new ScopeExp(loc, imp.pkg);
949 1
        return ie.expressionSemantic(sc);
950
    }
951 1
    if (Package pkg = s.isPackage())
952
    {
953 1
        auto ie = new ScopeExp(loc, pkg);
954 1
        return ie.expressionSemantic(sc);
955
    }
956 1
    if (Module mod = s.isModule())
957
    {
958 0
        auto ie = new ScopeExp(loc, mod);
959 0
        return ie.expressionSemantic(sc);
960
    }
961 1
    if (Nspace ns = s.isNspace())
962
    {
963 1
        auto ie = new ScopeExp(loc, ns);
964 1
        return ie.expressionSemantic(sc);
965
    }
966

967 1
    if (Type t = s.getType())
968
    {
969 1
        return (new TypeExp(loc, t)).expressionSemantic(sc);
970
    }
971

972 1
    if (TupleDeclaration tup = s.isTupleDeclaration())
973
    {
974 1
        if (tup.needThis() && hasThis(sc))
975 1
            e = new DotVarExp(loc, new ThisExp(loc), tup);
976
        else
977 1
            e = new TupleExp(loc, tup);
978 1
        e = e.expressionSemantic(sc);
979 1
        return e;
980
    }
981

982 1
    if (TemplateInstance ti = s.isTemplateInstance())
983
    {
984 1
        ti.dsymbolSemantic(sc);
985 1
        if (!ti.inst || ti.errors)
986 0
            return ErrorExp.get();
987 1
        s = ti.toAlias();
988 1
        if (!s.isTemplateInstance())
989 0
            goto Lagain;
990 1
        e = new ScopeExp(loc, ti);
991 1
        e = e.expressionSemantic(sc);
992 1
        return e;
993
    }
994 1
    if (TemplateDeclaration td = s.isTemplateDeclaration())
995
    {
996 1
        Dsymbol p = td.toParentLocal();
997 1
        FuncDeclaration fdthis = hasThis(sc);
998 1
        AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
999 1
        if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
1000
        {
1001 1
            e = new DotTemplateExp(loc, new ThisExp(loc), td);
1002
        }
1003
        else
1004 1
            e = new TemplateExp(loc, td);
1005 1
        e = e.expressionSemantic(sc);
1006 1
        return e;
1007
    }
1008

1009 0
    .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars());
1010 0
    return ErrorExp.get();
1011
}
1012

1013
/*************************************************************
1014
 * Given var, get the
1015
 * right `this` pointer if var is in an outer class, but our
1016
 * existing `this` pointer is in an inner class.
1017
 * Params:
1018
 *      loc = location to use for error messages
1019
 *      sc = context
1020
 *      ad = struct or class we need the correct `this` for
1021
 *      e1 = existing `this`
1022
 *      var = the specific member of ad we're accessing
1023
 *      flag = if true, return `null` instead of throwing an error
1024
 * Returns:
1025
 *      Expression representing the `this` for the var
1026
 */
1027
private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0)
1028
{
1029
    //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
1030
L1:
1031 1
    Type t = e1.type.toBasetype();
1032
    //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
1033

1034 1
    if (e1.op == TOK.objcClassReference)
1035
    {
1036
        // We already have an Objective-C class reference, just use that as 'this'.
1037 0
        return e1;
1038
    }
1039 1
    else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc &&
1040 0
             var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
1041 0
             var.isFuncDeclaration.selector)
1042
    {
1043 0
        return new ObjcClassReferenceExp(e1.loc, cast(ClassDeclaration) ad);
1044
    }
1045

1046
    /* Access of a member which is a template parameter in dual-scope scenario
1047
     * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
1048
     * class B {int m; inc() { new A().inc!m(); } }
1049
     */
1050 1
    if (e1.op == TOK.this_)
1051
    {
1052 1
        FuncDeclaration f = hasThis(sc);
1053 1
        if (f && f.isThis2)
1054
        {
1055 1
            if (f.followInstantiationContext(ad))
1056
            {
1057 1
                e1 = new VarExp(loc, f.vthis);
1058 1
                e1 = new PtrExp(loc, e1);
1059 1
                e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
1060 1
                e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
1061 1
                if (e1.op == TOK.error)
1062 0
                    return e1;
1063 1
                goto L1;
1064
            }
1065
        }
1066
    }
1067

1068
    /* If e1 is not the 'this' pointer for ad
1069
     */
1070 1
    if (ad &&
1071 1
        !(t.ty == Tpointer && t.nextOf().ty == Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) &&
1072 1
        !(t.ty == Tstruct && (cast(TypeStruct)t).sym == ad))
1073
    {
1074 1
        ClassDeclaration cd = ad.isClassDeclaration();
1075 1
        ClassDeclaration tcd = t.isClassHandle();
1076

1077
        /* e1 is the right this if ad is a base class of e1
1078
         */
1079 1
        if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
1080
        {
1081
            /* Only classes can be inner classes with an 'outer'
1082
             * member pointing to the enclosing class instance
1083
             */
1084 1
            if (tcd && tcd.isNested())
1085
            {
1086
                /* e1 is the 'this' pointer for an inner class: tcd.
1087
                 * Rewrite it as the 'this' pointer for the outer class.
1088
                 */
1089 1
                auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
1090 1
                e1 = new DotVarExp(loc, e1, vthis);
1091 1
                e1.type = vthis.type;
1092 1
                e1.type = e1.type.addMod(t.mod);
1093
                // Do not call ensureStaticLinkTo()
1094
                //e1 = e1.semantic(sc);
1095

1096
                // Skip up over nested functions, and get the enclosing
1097
                // class type.
1098 1
                e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
1099 1
                if (e1.op == TOK.error)
1100 1
                    return e1;
1101 1
                goto L1;
1102
            }
1103

1104
            /* Can't find a path from e1 to ad
1105
             */
1106 1
            if (flag)
1107 1
                return null;
1108 1
            e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
1109 1
            return ErrorExp.get();
1110
        }
1111
    }
1112 1
    return e1;
1113
}
1114

1115
/***************************************
1116
 * Pull out any properties.
1117
 */
1118
private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
1119
{
1120
    //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null);
1121 1
    Loc loc = e1.loc;
1122

1123 1
    OverloadSet os;
1124 1
    Dsymbol s;
1125 1
    Objects* tiargs;
1126 1
    Type tthis;
1127 1
    if (e1.op == TOK.dot)
1128
    {
1129 1
        DotExp de = cast(DotExp)e1;
1130 1
        if (de.e2.op == TOK.overloadSet)
1131
        {
1132 1
            tiargs = null;
1133 1
            tthis = de.e1.type;
1134 1
            os = (cast(OverExp)de.e2).vars;
1135 1
            goto Los;
1136
        }
1137
    }
1138 1
    else if (e1.op == TOK.overloadSet)
1139
    {
1140 1
        tiargs = null;
1141 1
        tthis = null;
1142 1
        os = (cast(OverExp)e1).vars;
1143
    Los:
1144 1
        assert(os);
1145 1
        FuncDeclaration fd = null;
1146 1
        if (e2)
1147
        {
1148 1
            e2 = e2.expressionSemantic(sc);
1149 1
            if (e2.op == TOK.error)
1150 0
                return ErrorExp.get();
1151 1
            e2 = resolveProperties(sc, e2);
1152

1153 1
            Expressions a;
1154 1
            a.push(e2);
1155

1156 1
            for (size_t i = 0; i < os.a.dim; i++)
1157
            {
1158 1
                if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
1159
                {
1160 1
                    if (f.errors)
1161 0
                        return ErrorExp.get();
1162 1
                    fd = f;
1163 1
                    assert(fd.type.ty == Tfunction);
1164
                }
1165
            }
1166 1
            if (fd)
1167
            {
1168 1
                Expression e = new CallExp(loc, e1, e2);
1169 1
                return e.expressionSemantic(sc);
1170
            }
1171
        }
1172
        {
1173 1
            for (size_t i = 0; i < os.a.dim; i++)
1174
            {
1175 1
                if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
1176
                {
1177 1
                    if (f.errors)
1178 0
                        return ErrorExp.get();
1179 1
                    fd = f;
1180 1
                    assert(fd.type.ty == Tfunction);
1181 1
                    TypeFunction tf = cast(TypeFunction)fd.type;
1182 1
                    if (!tf.isref && e2)
1183
                    {
1184 1
                        error(loc, "%s is not an lvalue", e1.toChars());
1185 1
                        return ErrorExp.get();
1186
                    }
1187
                }
1188
            }
1189 1
            if (fd)
1190
            {
1191 1
                Expression e = new CallExp(loc, e1);
1192 1
                if (e2)
1193 0
                    e = new AssignExp(loc, e, e2);
1194 1
                return e.expressionSemantic(sc);
1195
            }
1196
        }
1197 0
        if (e2)
1198 0
            goto Leprop;
1199
    }
1200 1
    else if (e1.op == TOK.dotTemplateInstance)
1201
    {
1202 1
        DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1;
1203 1
        if (!dti.findTempDecl(sc))
1204 0
            goto Leprop;
1205 1
        if (!dti.ti.semanticTiargs(sc))
1206 0
            goto Leprop;
1207 1
        tiargs = dti.ti.tiargs;
1208 1
        tthis = dti.e1.type;
1209 1
        if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
1210 1
            goto Los;
1211 1
        if ((s = dti.ti.tempdecl) !is null)
1212 1
            goto Lfd;
1213
    }
1214 1
    else if (e1.op == TOK.dotTemplateDeclaration)
1215
    {
1216 1
        DotTemplateExp dte = cast(DotTemplateExp)e1;
1217 1
        s = dte.td;
1218 1
        tiargs = null;
1219 1
        tthis = dte.e1.type;
1220 1
        goto Lfd;
1221
    }
1222 1
    else if (e1.op == TOK.scope_)
1223
    {
1224 1
        s = (cast(ScopeExp)e1).sds;
1225 1
        TemplateInstance ti = s.isTemplateInstance();
1226 1
        if (ti && !ti.semanticRun && ti.tempdecl)
1227
        {
1228
            //assert(ti.needsTypeInference(sc));
1229 1
            if (!ti.semanticTiargs(sc))
1230 0
                goto Leprop;
1231 1
            tiargs = ti.tiargs;
1232 1
            tthis = null;
1233 1
            if ((os = ti.tempdecl.isOverloadSet()) !is null)
1234 0
                goto Los;
1235 1
            if ((s = ti.tempdecl) !is null)
1236 1
                goto Lfd;
1237
        }
1238
    }
1239 1
    else if (e1.op == TOK.template_)
1240
    {
1241 1
        s = (cast(TemplateExp)e1).td;
1242 1
        tiargs = null;
1243 1
        tthis = null;
1244 1
        goto Lfd;
1245
    }
1246 1
    else if (e1.op == TOK.dotVariable && e1.type && e1.type.toBasetype().ty == Tfunction)
1247
    {
1248 1
        DotVarExp dve = cast(DotVarExp)e1;
1249 1
        s = dve.var.isFuncDeclaration();
1250 1
        tiargs = null;
1251 1
        tthis = dve.e1.type;
1252 1
        goto Lfd;
1253
    }
1254 1
    else if (e1.op == TOK.variable && e1.type && e1.type.toBasetype().ty == Tfunction)
1255
    {
1256 1
        s = (cast(VarExp)e1).var.isFuncDeclaration();
1257 1
        tiargs = null;
1258 1
        tthis = null;
1259
    Lfd:
1260 1
        assert(s);
1261 1
        if (e2)
1262
        {
1263 1
            e2 = e2.expressionSemantic(sc);
1264 1
            if (e2.op == TOK.error)
1265 1
                return ErrorExp.get();
1266 1
            e2 = resolveProperties(sc, e2);
1267

1268 1
            Expressions a;
1269 1
            a.push(e2);
1270

1271 1
            FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet);
1272 1
            if (fd && fd.type)
1273
            {
1274 1
                if (fd.errors)
1275 0
                    return ErrorExp.get();
1276 1
                assert(fd.type.ty == Tfunction);
1277 1
                Expression e = new CallExp(loc, e1, e2);
1278 1
                return e.expressionSemantic(sc);
1279
            }
1280
        }
1281
        {
1282 1
            FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1283 1
            if (fd && fd.type)
1284
            {
1285 1
                if (fd.errors)
1286 1
                    return ErrorExp.get();
1287 1
                assert(fd.type.ty == Tfunction);
1288 1
                TypeFunction tf = cast(TypeFunction)fd.type;
1289 1
                if (!e2 || tf.isref)
1290
                {
1291 1
                    Expression e = new CallExp(loc, e1);
1292 1
                    if (e2)
1293 1
                        e = new AssignExp(loc, e, e2);
1294 1
                    return e.expressionSemantic(sc);
1295
                }
1296
            }
1297
        }
1298 1
        if (FuncDeclaration fd = s.isFuncDeclaration())
1299
        {
1300
            // Keep better diagnostic message for invalid property usage of functions
1301 1
            assert(fd.type.ty == Tfunction);
1302 1
            Expression e = new CallExp(loc, e1, e2);
1303 1
            return e.expressionSemantic(sc);
1304
        }
1305 1
        if (e2)
1306 1
            goto Leprop;
1307
    }
1308 1
    if (e1.op == TOK.variable)
1309
    {
1310 1
        VarExp ve = cast(VarExp)e1;
1311 1
        VarDeclaration v = ve.var.isVarDeclaration();
1312 1
        if (v && ve.checkPurity(sc, v))
1313 1
            return ErrorExp.get();
1314
    }
1315 1
    if (e2)
1316 1
        return null;
1317

1318 1
    if (e1.type && e1.op != TOK.type) // function type is not a property
1319
    {
1320
        /* Look for e1 being a lazy parameter; rewrite as delegate call
1321
         * only if the symbol wasn't already treated as a delegate
1322
         */
1323 1
        auto ve = e1.isVarExp();
1324 1
        if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1325
        {
1326 1
                Expression e = new CallExp(loc, e1);
1327 1
                return e.expressionSemantic(sc);
1328
        }
1329 1
        else if (e1.op == TOK.dotVariable)
1330
        {
1331
            // Check for reading overlapped pointer field in @safe code.
1332 1
            if (checkUnsafeAccess(sc, e1, true, true))
1333 1
                return ErrorExp.get();
1334
        }
1335 1
        else if (e1.op == TOK.dot)
1336
        {
1337 1
            e1.error("expression has no value");
1338 1
            return ErrorExp.get();
1339
        }
1340 1
        else if (e1.op == TOK.call)
1341
        {
1342 1
            CallExp ce = cast(CallExp)e1;
1343
            // Check for reading overlapped pointer field in @safe code.
1344 1
            if (checkUnsafeAccess(sc, ce.e1, true, true))
1345 1
                return ErrorExp.get();
1346
        }
1347
    }
1348

1349 1
    if (!e1.type)
1350
    {
1351 1
        error(loc, "cannot resolve type for %s", e1.toChars());
1352 1
        e1 = ErrorExp.get();
1353
    }
1354 1
    return e1;
1355

1356
Leprop:
1357 1
    error(loc, "not a property %s", e1.toChars());
1358 1
    return ErrorExp.get();
1359
}
1360

1361
extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1362
{
1363
    //printf("resolveProperties(%s)\n", e.toChars());
1364 1
    e = resolvePropertiesX(sc, e);
1365 1
    if (e.checkRightThis(sc))
1366 1
        return ErrorExp.get();
1367 1
    return e;
1368
}
1369

1370
/****************************************
1371
 * The common type is determined by applying ?: to each pair.
1372
 * Output:
1373
 *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
1374
 *      *pt     if pt is not NULL, set to the common type
1375
 * Returns:
1376
 *      true    a semantic error was detected
1377
 */
1378
private bool arrayExpressionToCommonType(Scope* sc, Expressions* exps, Type* pt)
1379
{
1380
    /* Still have a problem with:
1381
     *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
1382
     * which works if the array literal is initialized top down with the ubyte[][]
1383
     * type, but fails with this function doing bottom up typing.
1384
     */
1385

1386
    //printf("arrayExpressionToCommonType()\n");
1387 1
    scope IntegerExp integerexp = IntegerExp.literal!0;
1388 1
    scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1389

1390 1
    Type t0 = null;
1391 1
    Expression e0 = null;
1392 1
    size_t j0 = ~0;
1393 1
    bool foundType;
1394

1395 1
    for (size_t i = 0; i < exps.dim; i++)
1396
    {
1397 1
        Expression e = (*exps)[i];
1398 1
        if (!e)
1399 1
            continue;
1400

1401 1
        e = resolveProperties(sc, e);
1402 1
        if (!e.type)
1403
        {
1404 0
            e.error("`%s` has no value", e.toChars());
1405 0
            t0 = Type.terror;
1406 0
            continue;
1407
        }
1408 1
        if (e.op == TOK.type)
1409
        {
1410 1
            foundType = true; // do not break immediately, there might be more errors
1411 1
            e.checkValue(); // report an error "type T has no value"
1412 1
            t0 = Type.terror;
1413 1
            continue;
1414
        }
1415 1
        if (e.type.ty == Tvoid)
1416
        {
1417
            // void expressions do not concur to the determination of the common
1418
            // type.
1419 1
            continue;
1420
        }
1421 1
        if (checkNonAssignmentArrayOp(e))
1422
        {
1423 1
            t0 = Type.terror;
1424 1
            continue;
1425
        }
1426

1427 1
        e = doCopyOrMove(sc, e);
1428

1429 1
        if (!foundType && t0 && !t0.equals(e.type))
1430
        {
1431
            /* This applies ?: to merge the types. It's backwards;
1432
             * ?: should call this function to merge types.
1433
             */
1434 1
            condexp.type = null;
1435 1
            condexp.e1 = e0;
1436 1
            condexp.e2 = e;
1437 1
            condexp.loc = e.loc;
1438 1
            Expression ex = condexp.expressionSemantic(sc);
1439 1
            if (ex.op == TOK.error)
1440 1
                e = ex;
1441
            else
1442
            {
1443
                // Convert to common type
1444 1
                (*exps)[j0] = condexp.e1.castTo(sc, condexp.type);
1445 1
                e = condexp.e2.castTo(sc, condexp.type);
1446
            }
1447
        }
1448 1
        j0 = i;
1449 1
        e0 = e;
1450 1
        t0 = e.type;
1451 1
        if (e.op != TOK.error)
1452 1
            (*exps)[i] = e;
1453
    }
1454

1455 1
    if (!t0)
1456 1
        t0 = Type.tvoid; // [] is typed as void[]
1457 1
    else if (t0.ty != Terror)
1458
    {
1459 1
        for (size_t i = 0; i < exps.dim; i++)
1460
        {
1461 1
            Expression e = (*exps)[i];
1462 1
            if (!e)
1463 1
                continue;
1464

1465 1
            e = e.implicitCastTo(sc, t0);
1466
            //assert(e.op != TOK.error);
1467 1
            if (e.op == TOK.error)
1468
            {
1469
                /* https://issues.dlang.org/show_bug.cgi?id=13024
1470
                 * a workaround for the bug in typeMerge -
1471
                 * it should paint e1 and e2 by deduced common type,
1472
                 * but doesn't in this particular case.
1473
                 */
1474 1
                t0 = Type.terror;
1475 1
                break;
1476
            }
1477 1
            (*exps)[i] = e;
1478
        }
1479
    }
1480 1
    if (pt)
1481 1
        *pt = t0;
1482

1483 1
    return (t0 == Type.terror);
1484
}
1485

1486
private Expression opAssignToOp(const ref Loc loc, TOK op, Expression e1, Expression e2)
1487
{
1488 1
    Expression e;
1489 1
    switch (op)
1490
    {
1491 1
    case TOK.addAssign:
1492 1
        e = new AddExp(loc, e1, e2);
1493 1
        break;
1494

1495 1
    case TOK.minAssign:
1496 1
        e = new MinExp(loc, e1, e2);
1497 1
        break;
1498

1499 1
    case TOK.mulAssign:
1500 1
        e = new MulExp(loc, e1, e2);
1501 1
        break;
1502

1503 1
    case TOK.divAssign:
1504 1
        e = new DivExp(loc, e1, e2);
1505 1
        break;
1506

1507 1
    case TOK.modAssign:
1508 1
        e = new ModExp(loc, e1, e2);
1509 1
        break;
1510

1511 1
    case TOK.andAssign:
1512 1
        e = new AndExp(loc, e1, e2);
1513 1
        break;
1514

1515 1
    case TOK.orAssign:
1516 1
        e = new OrExp(loc, e1, e2);
1517 1
        break;
1518

1519 1
    case TOK.xorAssign:
1520 1
        e = new XorExp(loc, e1, e2);
1521 1
        break;
1522

1523 1
    case TOK.leftShiftAssign:
1524 1
        e = new ShlExp(loc, e1, e2);
1525 1
        break;
1526

1527 1
    case TOK.rightShiftAssign:
1528 1
        e = new ShrExp(loc, e1, e2);
1529 1
        break;
1530

1531 1
    case TOK.unsignedRightShiftAssign:
1532 1
        e = new UshrExp(loc, e1, e2);
1533 1
        break;
1534

1535 0
    default:
1536 0
        assert(0);
1537
    }
1538 1
    return e;
1539
}
1540

1541
/*********************
1542
 * Rewrite:
1543
 *    array.length op= e2
1544
 * as:
1545
 *    array.length = array.length op e2
1546
 * or:
1547
 *    auto tmp = &array;
1548
 *    (*tmp).length = (*tmp).length op e2
1549
 */
1550
private Expression rewriteOpAssign(BinExp exp)
1551
{
1552 1
    Expression e;
1553

1554 1
    assert(exp.e1.op == TOK.arrayLength);
1555 1
    ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
1556 1
    if (ale.e1.op == TOK.variable)
1557
    {
1558 1
        e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1559 1
        e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1560
    }
1561
    else
1562
    {
1563
        /*    auto tmp = &array;
1564
         *    (*tmp).length = (*tmp).length op e2
1565
         */
1566 1
        auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1567

1568 1
        Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1569 1
        Expression elvalue = e1.syntaxCopy();
1570 1
        e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1571 1
        e = new AssignExp(exp.loc, elvalue, e);
1572 1
        e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1573
    }
1574 1
    return e;
1575
}
1576

1577
/****************************************
1578
 * Preprocess arguments to function.
1579
 * Input:
1580
 *      reportErrors    whether or not to report errors here.  Some callers are not
1581
 *                      checking actual function params, so they'll do their own error reporting
1582
 * Output:
1583
 *      exps[]  tuples expanded, properties resolved, rewritten in place
1584
 * Returns:
1585
 *      true    a semantic error occurred
1586
 */
1587
private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1588
{
1589 1
    bool err = false;
1590 1
    if (exps)
1591
    {
1592 1
        expandTuples(exps);
1593

1594 1
        for (size_t i = 0; i < exps.dim; i++)
1595
        {
1596 1
            Expression arg = (*exps)[i];
1597 1
            arg = resolveProperties(sc, arg);
1598 1
            if (arg.op == TOK.type)
1599
            {
1600
                // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1601 1
                arg = resolveAliasThis(sc, arg);
1602

1603 1
                if (arg.op == TOK.type)
1604
                {
1605 1
                    if (reportErrors)
1606
                    {
1607 1
                        arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1608 1
                        arg = ErrorExp.get();
1609
                    }
1610 1
                    err = true;
1611
                }
1612
            }
1613 1
            else if (arg.type.toBasetype().ty == Tfunction)
1614
            {
1615 1
                if (reportErrors)
1616
                {
1617 1
                    arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1618 1
                    arg = ErrorExp.get();
1619
                }
1620 1
                err = true;
1621
            }
1622 1
            else if (checkNonAssignmentArrayOp(arg))
1623
            {
1624 1
                arg = ErrorExp.get();
1625 1
                err = true;
1626
            }
1627 1
            (*exps)[i] = arg;
1628
        }
1629
    }
1630 1
    return err;
1631
}
1632

1633
/********************************************
1634
 * Issue an error if default construction is disabled for type t.
1635
 * Default construction is required for arrays and 'out' parameters.
1636
 * Returns:
1637
 *      true    an error was issued
1638
 */
1639
private bool checkDefCtor(Loc loc, Type t)
1640
{
1641 1
    t = t.baseElemOf();
1642 1
    if (t.ty == Tstruct)
1643
    {
1644 1
        StructDeclaration sd = (cast(TypeStruct)t).sym;
1645 1
        if (sd.noDefaultCtor)
1646
        {
1647 1
            sd.error(loc, "default construction is disabled");
1648 1
            return true;
1649
        }
1650
    }
1651 1
    return false;
1652
}
1653

1654
/****************************************
1655
 * Now that we know the exact type of the function we're calling,
1656
 * the arguments[] need to be adjusted:
1657
 *      1. implicitly convert argument to the corresponding parameter type
1658
 *      2. add default arguments for any missing arguments
1659
 *      3. do default promotions on arguments corresponding to ...
1660
 *      4. add hidden _arguments[] argument
1661
 *      5. call copy constructor for struct value arguments
1662
 * Params:
1663
 *      loc       = location of function call
1664
 *      sc        = context
1665
 *      tf        = type of the function
1666
 *      ethis     = `this` argument, `null` if none or not known
1667
 *      tthis     = type of `this` argument, `null` if no `this` argument
1668
 *      arguments = array of actual arguments to function call
1669
 *      fd        = the function being called, `null` if called indirectly
1670
 *      prettype  = set to return type of function
1671
 *      peprefix  = set to expression to execute before `arguments[]` are evaluated, `null` if none
1672
 * Returns:
1673
 *      true    errors happened
1674
 */
1675
private bool functionParameters(const ref Loc loc, Scope* sc,
1676
    TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1677
    Type* prettype, Expression* peprefix)
1678
{
1679
    //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1680 1
    assert(arguments);
1681 1
    assert(fd || tf.next);
1682 1
    size_t nargs = arguments ? arguments.dim : 0;
1683 1
    const size_t nparams = tf.parameterList.length;
1684 1
    const olderrors = global.errors;
1685 1
    bool err = false;
1686 1
    *prettype = Type.terror;
1687 1
    Expression eprefix = null;
1688 1
    *peprefix = null;
1689

1690 1
    if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1691
    {
1692 0
        error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1693 0
        return true;
1694
    }
1695

1696
    // If inferring return type, and semantic3() needs to be run if not already run
1697 1
    if (!tf.next && fd.inferRetType)
1698
    {
1699 1
        fd.functionSemantic();
1700
    }
1701 1
    else if (fd && fd.parent)
1702
    {
1703 1
        TemplateInstance ti = fd.parent.isTemplateInstance();
1704 1
        if (ti && ti.tempdecl)
1705
        {
1706 1
            fd.functionSemantic3();
1707
        }
1708
    }
1709

1710
    /* If calling a pragma(inline, true) function,
1711
     * set flag to later scan for inlines.
1712
     */
1713 1
    if (fd && fd.inlining == PINLINE.always)
1714
    {
1715 1
        if (sc._module)
1716 1
            sc._module.hasAlwaysInlines = true;
1717 1
        if (sc.func)
1718 1
            sc.func.hasAlwaysInlines = true;
1719
    }
1720

1721 1
    const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1722

1723 1
    const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1724

1725
    /* If the function return type has wildcards in it, we'll need to figure out the actual type
1726
     * based on the actual argument types.
1727
     * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1728
     * of the arguments.
1729
     */
1730 1
    MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1731

1732 1
    bool done = false;
1733 1
    foreach (const i; 0 .. n)
1734
    {
1735 1
        Expression arg = (i < nargs) ? (*arguments)[i] : null;
1736

1737 1
        if (i < nparams)
1738
        {
1739
            bool errorArgs()
1740
            {
1741 0
                error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1742 0
                return true;
1743
            }
1744

1745 1
            Parameter p = tf.parameterList[i];
1746 1
            const bool isRef = p.isReference();
1747

1748 1
            if (!arg)
1749
            {
1750 1
                if (!p.defaultArg)
1751
                {
1752 1
                    if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1753 1
                        goto L2;
1754 0
                    return errorArgs();
1755
                }
1756 1
                arg = p.defaultArg;
1757 1
                arg = inlineCopy(arg, sc);
1758
                // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1759 1
                arg = arg.resolveLoc(loc, sc);
1760 1
                arguments.push(arg);
1761 1
                nargs++;
1762
            }
1763
            else
1764
            {
1765 1
                if (arg.op == TOK.default_)
1766
                {
1767 1
                    arg = arg.resolveLoc(loc, sc);
1768 1
                    (*arguments)[i] = arg;
1769
                }
1770
            }
1771

1772

1773 1
            if (isRef && !p.type.isConst && !p.type.isImmutable
1774 1
                && (p.storageClass & STC.const_) != STC.const_
1775 1
                && (p.storageClass & STC.immutable_) != STC.immutable_
1776 1
                && checkIfIsStructLiteralDotExpr(arg))
1777 1
                    break;
1778

1779 1
            if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1780
            {
1781
                //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1782
                {
1783 1
                    MATCH m;
1784 1
                    if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1785
                    {
1786 1
                        if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1787 1
                            goto L2;
1788 1
                        else if (nargs != nparams)
1789 0
                            return errorArgs();
1790 1
                        goto L1;
1791
                    }
1792
                }
1793
            L2:
1794 1
                Type tb = p.type.toBasetype();
1795 1
                switch (tb.ty)
1796
                {
1797 1
                case Tsarray:
1798 1
                case Tarray:
1799
                    {
1800
                        /* Create a static array variable v of type arg.type:
1801
                         *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1802
                         *
1803
                         * The array literal in the initializer of the hidden variable
1804
                         * is now optimized.
1805
                         * https://issues.dlang.org/show_bug.cgi?id=2356
1806
                         */
1807 1
                        Type tbn = (cast(TypeArray)tb).next;    // array element type
1808 1
                        Type tret = p.isLazyArray();
1809

1810 1
                        auto elements = new Expressions(nargs - i);
1811 1
                        foreach (u; 0 .. elements.dim)
1812
                        {
1813 1
                            Expression a = (*arguments)[i + u];
1814 1
                            if (tret && a.implicitConvTo(tret))
1815
                            {
1816
                                // p is a lazy array of delegates, tret is return type of the delegates
1817 1
                                a = a.implicitCastTo(sc, tret)
1818
                                     .optimize(WANTvalue)
1819
                                     .toDelegate(tret, sc);
1820
                            }
1821
                            else
1822 1
                                a = a.implicitCastTo(sc, tbn);
1823 1
                            a = a.addDtorHook(sc);
1824 1
                            (*elements)[u] = a;
1825
                        }
1826
                        // https://issues.dlang.org/show_bug.cgi?id=14395
1827
                        // Convert to a static array literal, or its slice.
1828 1
                        arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1829 1
                        if (tb.ty == Tarray)
1830
                        {
1831 1
                            arg = new SliceExp(loc, arg, null, null);
1832 1
                            arg.type = p.type;
1833
                        }
1834 1
                        break;
1835
                    }
1836 1
                case Tclass:
1837
                    {
1838
                        /* Set arg to be:
1839
                         *      new Tclass(arg0, arg1, ..., argn)
1840
                         */
1841 1
                        auto args = new Expressions(nargs - i);
1842 1
                        foreach (u; i .. nargs)
1843 1
                            (*args)[u - i] = (*arguments)[u];
1844 1
                        arg = new NewExp(loc, null, null, p.type, args);
1845 1
                        break;
1846
                    }
1847 0
                default:
1848 0
                    if (!arg)
1849
                    {
1850 0
                        error(loc, "not enough arguments");
1851 0
                        return true;
1852
                    }
1853 0
                    break;
1854
                }
1855 1
                arg = arg.expressionSemantic(sc);
1856
                //printf("\targ = '%s'\n", arg.toChars());
1857 1
                arguments.setDim(i + 1);
1858 1
                (*arguments)[i] = arg;
1859 1
                nargs = i + 1;
1860 1
                done = true;
1861
            }
1862

1863
        L1:
1864 1
            if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1865
            {
1866

1867 1
                if (ubyte wm = arg.type.deduceWild(p.type, isRef))
1868
                {
1869 1
                    wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1870
                    //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1871
                }
1872
            }
1873
        }
1874 1
        if (done)
1875 1
            break;
1876
    }
1877 1
    if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1878 1
        tf.next && tf.next.hasWild() &&
1879 1
        (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1880
    {
1881
        bool errorInout(MOD wildmatch)
1882
        {
1883 1
            const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1884 1
            error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1885 1
            return true;
1886
        }
1887

1888 1
        if (fd)
1889
        {
1890
            /* If the called function may return the reference to
1891
             * outer inout data, it should be rejected.
1892
             *
1893
             * void foo(ref inout(int) x) {
1894
             *   ref inout(int) bar(inout(int)) { return x; }
1895
             *   struct S {
1896
             *      ref inout(int) bar() inout { return x; }
1897
             *      ref inout(int) baz(alias a)() inout { return x; }
1898
             *   }
1899
             *   bar(int.init) = 1;  // bad!
1900
             *   S().bar() = 1;      // bad!
1901
             * }
1902
             * void test() {
1903
             *   int a;
1904
             *   auto s = foo(a);
1905
             *   s.baz!a() = 1;      // bad!
1906
             * }
1907
             *
1908
             */
1909
            bool checkEnclosingWild(Dsymbol s)
1910
            {
1911
                bool checkWild(Dsymbol s)
1912
                {
1913 1
                    if (!s)
1914 0
                        return false;
1915 1
                    if (auto ad = s.isAggregateDeclaration())
1916
                    {
1917 1
                        if (ad.isNested())
1918 1
                            return checkEnclosingWild(s);
1919
                    }
1920 1
                    else if (auto ff = s.isFuncDeclaration())
1921
                    {
1922 1
                        if ((cast(TypeFunction)ff.type).iswild)
1923 1
                            return errorInout(wildmatch);
1924

1925 1
                        if (ff.isNested() || ff.isThis())
1926 1
                            return checkEnclosingWild(s);
1927
                    }
1928 1
                    return false;
1929
                }
1930

1931 1
                Dsymbol ctx0 = s.toParent2();
1932 1
                Dsymbol ctx1 = s.toParentLocal();
1933 1
                if (checkWild(ctx0))
1934 1
                    return true;
1935 1
                if (ctx0 != ctx1)
1936 1
                    return checkWild(ctx1);
1937 1
                return false;
1938
            }
1939 1
            if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1940 1
                return true;
1941
        }
1942 1
        else if (tf.isWild())
1943 1
            return errorInout(wildmatch);
1944
    }
1945

1946 1
    Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1947 1
                           tthis &&
1948 1
                           tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1949 1
                           tthis.hasPointers())
1950 1
                          ? ethis : null;
1951

1952 1
    assert(nargs >= nparams);
1953 1
    foreach (const i, arg; (*arguments)[0 .. nargs])
1954
    {
1955 1
        assert(arg);
1956 1
        if (i < nparams)
1957
        {
1958 1
            Parameter p = tf.parameterList[i];
1959 1
            Type targ = arg.type;               // keep original type for isCopyable() because alias this
1960
                                                // resolution may hide an uncopyable type
1961

1962 1
            if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1963
            {
1964 1
                Type tprm = p.type.hasWild()
1965 1
                    ? p.type.substWildTo(wildmatch)
1966 1
                    : p.type;
1967

1968 1
                const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor;
1969 1
                const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
1970 1
                if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
1971
                {
1972
                    //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
1973 1
                    arg = arg.implicitCastTo(sc, tprm);
1974 1
                    arg = arg.optimize(WANTvalue, p.isReference());
1975
                }
1976
            }
1977 1
            if (p.storageClass & STC.ref_)
1978
            {
1979 1
                if (global.params.rvalueRefParam &&
1980 1
                    !arg.isLvalue() &&
1981 1
                    targ.isCopyable())
1982
                {   /* allow rvalues to be passed to ref parameters by copying
1983
                     * them to a temp, then pass the temp as the argument
1984
                     */
1985 1
                    auto v = copyToTemp(0, "__rvalue", arg);
1986 1
                    Expression ev = new DeclarationExp(arg.loc, v);
1987 1
                    ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
1988 1
                    arg = ev.expressionSemantic(sc);
1989
                }
1990 1
                arg = arg.toLvalue(sc, arg);
1991

1992
                // Look for mutable misaligned pointer, etc., in @safe mode
1993 1
                err |= checkUnsafeAccess(sc, arg, false, true);
1994
            }
1995 1
            else if (p.storageClass & STC.out_)
1996
            {
1997 1
                Type t = arg.type;
1998 1
                if (!t.isMutable() || !t.isAssignable()) // check blit assignable
1999
                {
2000 1
                    arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
2001 1
                    err = true;
2002
                }
2003
                else
2004
                {
2005
                    // Look for misaligned pointer, etc., in @safe mode
2006 1
                    err |= checkUnsafeAccess(sc, arg, false, true);
2007 1
                    err |= checkDefCtor(arg.loc, t); // t must be default constructible
2008
                }
2009 1
                arg = arg.toLvalue(sc, arg);
2010
            }
2011 1
            else if (p.storageClass & STC.lazy_)
2012
            {
2013
                // Convert lazy argument to a delegate
2014 1
                auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2015 1
                arg = toDelegate(arg, t, sc);
2016
            }
2017
            //printf("arg: %s\n", arg.toChars());
2018
            //printf("type: %s\n", arg.type.toChars());
2019
            //printf("param: %s\n", p.toChars());
2020

2021 1
            if (firstArg && p.storageClass & STC.return_)
2022
            {
2023
                /* Argument value can be assigned to firstArg.
2024
                 * Check arg to see if it matters.
2025
                 */
2026 1
                if (global.params.vsafe)
2027 1
                    err |= checkParamArgumentReturn(sc, firstArg, arg, false);
2028
            }
2029 1
            else if (tf.parameterEscapes(tthis, p))
2030
            {
2031
                /* Argument value can escape from the called function.
2032
                 * Check arg to see if it matters.
2033
                 */
2034 1
                if (global.params.vsafe)
2035 1
                    err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
2036
            }
2037
            else
2038
            {
2039
                /* Argument value cannot escape from the called function.
2040
                 */
2041 1
                Expression a = arg;
2042 1
                if (a.op == TOK.cast_)
2043 1
                    a = (cast(CastExp)a).e1;
2044

2045 1
                ArrayLiteralExp ale;
2046 1
                if (p.type.toBasetype().ty == Tarray && !(p.storageClass & STC.return_) &&
2047 1
                    (ale = a.isArrayLiteralExp()) !is null)
2048
                {
2049
                    // allocate the array literal as temporary static array on the stack
2050 1
                    ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0);
2051 1
                    auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2052 1
                    auto declareTmp = new DeclarationExp(ale.loc, tmp);
2053 1
                    auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type);
2054 1
                    arg = CommaExp.combine(declareTmp, castToSlice);
2055 1
                    arg = arg.expressionSemantic(sc);
2056
                }
2057 1
                else if (a.op == TOK.function_)
2058
                {
2059
                    /* Function literals can only appear once, so if this
2060
                     * appearance was scoped, there cannot be any others.
2061
                     */
2062 1
                    FuncExp fe = cast(FuncExp)a;
2063 1
                    fe.fd.tookAddressOf = 0;
2064
                }
2065 1
                else if (a.op == TOK.delegate_)
2066
                {
2067
                    /* For passing a delegate to a scoped parameter,
2068
                     * this doesn't count as taking the address of it.
2069
                     * We only worry about 'escaping' references to the function.
2070
                     */
2071 1
                    DelegateExp de = cast(DelegateExp)a;
2072 1
                    if (de.e1.op == TOK.variable)
2073
                    {
2074 1
                        VarExp ve = cast(VarExp)de.e1;
2075 1
                        FuncDeclaration f = ve.var.isFuncDeclaration();
2076 1
                        if (f)
2077
                        {
2078 1
                            if (f.tookAddressOf)
2079 1
                                --f.tookAddressOf;
2080
                            //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2081
                        }
2082
                    }
2083
                }
2084
            }
2085 1
            if (!p.isReference())
2086 1
                err |= arg.checkSharedAccess(sc);
2087

2088 1
            arg = arg.optimize(WANTvalue, p.isReference());
2089

2090
            /* Determine if this parameter is the "first reference" parameter through which
2091
             * later "return" arguments can be stored.
2092
             */
2093 1
            if (i == 0 && !tthis && p.isReference() && p.type &&
2094 1
                (tf.next && tf.next.ty == Tvoid || isCtorCall))
2095
            {
2096 1
                Type tb = p.type.baseElemOf();
2097 1
                if (tb.isMutable() && tb.hasPointers())
2098
                {
2099 1
                    firstArg = arg;
2100
                }
2101
            }
2102
        }
2103
        else
2104
        {
2105
            // These will be the trailing ... arguments
2106
            // If not D linkage, do promotions
2107 1
            if (tf.linkage != LINK.d)
2108
            {
2109
                // Promote bytes, words, etc., to ints
2110 1
                arg = integralPromotions(arg, sc);
2111

2112
                // Promote floats to doubles
2113 1
                switch (arg.type.ty)
2114
                {
2115 1
                case Tfloat32:
2116 1
                    arg = arg.castTo(sc, Type.tfloat64);
2117 1
                    break;
2118

2119 1
                case Timaginary32:
2120 1
                    arg = arg.castTo(sc, Type.timaginary64);
2121 1
                    break;
2122

2123 1
                default:
2124 1
                    break;
2125
                }
2126 1
                if (tf.parameterList.varargs == VarArg.variadic)
2127
                {
2128 1
                    const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2129 1
                    if (arg.type.ty == Tarray)
2130
                    {
2131 1
                        arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2132 1
                        err = true;
2133
                    }
2134 1
                    if (arg.type.ty == Tsarray)
2135
                    {
2136 1
                        arg.error("cannot pass static arrays to `%s` vararg functions", p);
2137 1
                        err = true;
2138
                    }
2139
                }
2140
            }
2141

2142
            // Do not allow types that need destructors or copy constructors.
2143 1
            if (arg.type.needsDestruction())
2144
            {
2145 1
                arg.error("cannot pass types that need destruction as variadic arguments");
2146 1
                err = true;
2147
            }
2148 1
            if (arg.type.needsCopyOrPostblit())
2149
            {
2150 1
                arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2151 1
                err = true;
2152
            }
2153

2154
            // Convert static arrays to dynamic arrays
2155
            // BUG: I don't think this is right for D2
2156 1
            Type tb = arg.type.toBasetype();
2157 1
            if (tb.ty == Tsarray)
2158
            {
2159 1
                TypeSArray ts = cast(TypeSArray)tb;
2160 1
                Type ta = ts.next.arrayOf();
2161 1
                if (ts.size(arg.loc) == 0)
2162 0
                    arg = new NullExp(arg.loc, ta);
2163
                else
2164 1
                    arg = arg.castTo(sc, ta);
2165
            }
2166 1
            if (tb.ty == Tstruct)
2167
            {
2168
                //arg = callCpCtor(sc, arg);
2169
            }
2170
            // Give error for overloaded function addresses
2171 1
            if (arg.op == TOK.symbolOffset)
2172
            {
2173 1
                SymOffExp se = cast(SymOffExp)arg;
2174 1
                if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2175
                {
2176 1
                    arg.error("function `%s` is overloaded", arg.toChars());
2177 1
                    err = true;
2178
                }
2179
            }
2180 1
            err |= arg.checkValue();
2181 1
            err |= arg.checkSharedAccess(sc);
2182 1
            arg = arg.optimize(WANTvalue);
2183
        }
2184 1
        (*arguments)[i] = arg;
2185
    }
2186

2187
    /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2188
     */
2189 1
    const isVa_list = tf.parameterList.varargs == VarArg.none;
2190 1
    if (fd && fd.flags & FUNCFLAG.printf)
2191
    {
2192 1
        if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2193
        {
2194 1
            checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2195
        }
2196
    }
2197 1
    else if (fd && fd.flags & FUNCFLAG.scanf)
2198
    {
2199 1
        if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2200
        {
2201 1
            checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2202
        }
2203
    }
2204
    else
2205
    {
2206
        // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2207
    }
2208

2209
    /* Remaining problems:
2210
     * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2211
     *    implemented by calling a function) we'll defer this for now.
2212
     * 2. value structs (or static arrays of them) that need to be copy constructed
2213
     * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2214
     *    function gets called (functions normally destroy their parameters)
2215
     * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2216
     * up properly. Pushing arguments on the stack then cannot fail.
2217
     */
2218
    {
2219
        /* TODO: tackle problem 1)
2220
         */
2221 1
        const bool leftToRight = true; // TODO: Any cases that need rightToLeft?
2222 1
        if (!leftToRight)
2223 0
            assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2224

2225 1
        const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2226 1
        const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2227 1
        const ptrdiff_t step = (leftToRight ? 1 : -1);
2228

2229
        /* Compute indices of last throwing argument and first arg needing destruction.
2230
         * Used to not set up destructors unless an arg needs destruction on a throw
2231
         * in a later argument.
2232
         */
2233 1
        ptrdiff_t lastthrow = -1;
2234 1
        ptrdiff_t firstdtor = -1;
2235 1
        for (ptrdiff_t i = start; i != end; i += step)
2236
        {
2237 1
            Expression arg = (*arguments)[i];
2238 1
            if (canThrow(arg, sc.func, false))
2239 1
                lastthrow = i;
2240 1
            if (firstdtor == -1 && arg.type.needsDestruction())
2241
            {
2242 1
                Parameter p = (i >= nparams ? null : tf.parameterList[i]);
2243 1
                if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_))))
2244 1
                    firstdtor = i;
2245
            }
2246
        }
2247

2248
        /* Does problem 3) apply to this call?
2249
         */
2250 1
        const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
2251 1
            && (lastthrow - firstdtor) * step > 0);
2252

2253
        /* If so, initialize 'eprefix' by declaring the gate
2254
         */
2255 1
        VarDeclaration gate = null;
2256 1
        if (needsPrefix)
2257
        {
2258
            // eprefix => bool __gate [= false]
2259 1
            Identifier idtmp = Identifier.generateId("__gate");
2260 1
            gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2261 1
            gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2262 1
            gate.dsymbolSemantic(sc);
2263

2264 1
            auto ae = new DeclarationExp(loc, gate);
2265 1
            eprefix = ae.expressionSemantic(sc);
2266
        }
2267

2268 1
        for (ptrdiff_t i = start; i != end; i += step)
2269
        {
2270 1
            Expression arg = (*arguments)[i];
2271

2272 1
            Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2273 1
            const bool isRef = parameter && parameter.isReference();
2274 1
            const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
2275

2276
            /* Skip lazy parameters
2277
             */
2278 1
            if (isLazy)
2279 1
                continue;
2280

2281
            /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
2282
             * Declare a temporary variable for this arg and append that declaration to 'eprefix',
2283
             * which will implicitly take care of potential problem 2) for this arg.
2284
             * 'eprefix' will therefore finally contain all args up to and including the last
2285
             * potentially throwing arg, excluding all lazy parameters.
2286
             */
2287 1
            if (gate)
2288
            {
2289 1
                const bool needsDtor = (!isRef && arg.type.needsDestruction() && i != lastthrow);
2290

2291
                /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2292
                 */
2293 1
                auto tmp = copyToTemp(0,
2294 1
                    needsDtor ? "__pfx" : "__pfy",
2295 1
                    !isRef ? arg : arg.addressOf());
2296 1
                tmp.dsymbolSemantic(sc);
2297

2298
                /* Modify the destructor so it only runs if gate==false, i.e.,
2299
                 * only if there was a throw while constructing the args
2300
                 */
2301 1
                if (!needsDtor)
2302
                {
2303 1
                    if (tmp.edtor)
2304
                    {
2305 1
                        assert(i == lastthrow);
2306 1
                        tmp.edtor = null;
2307
                    }
2308
                }
2309
                else
2310
                {
2311
                    // edtor => (__gate || edtor)
2312 1
                    assert(tmp.edtor);
2313 1
                    Expression e = tmp.edtor;
2314 1
                    e = new LogicalExp(e.loc, TOK.orOr, new VarExp(e.loc, gate), e);
2315 1
                    tmp.edtor = e.expressionSemantic(sc);
2316
                    //printf("edtor: %s\n", tmp.edtor.toChars());
2317
                }
2318

2319
                // eprefix => (eprefix, auto __pfx/y = arg)
2320 1
                auto ae = new DeclarationExp(loc, tmp);
2321 1
                eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2322

2323
                // arg => __pfx/y
2324 1
                arg = new VarExp(loc, tmp);
2325 1
                arg = arg.expressionSemantic(sc);
2326 1
                if (isRef)
2327
                {
2328 1
                    arg = new PtrExp(loc, arg);
2329 1
                    arg = arg.expressionSemantic(sc);
2330
                }
2331

2332
                /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
2333
                 * i.e., disable the dtors right after constructing the last throwing arg.
2334
                 * From now on, the callee will take care of destructing the args because
2335
                 * the args are implicitly moved into function parameters.
2336
                 *
2337
                 * Set gate to null to let the next iterations know they don't need to
2338
                 * append to eprefix anymore.
2339
                 */
2340 1
                if (i == lastthrow)
2341
                {
2342 1
                    auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2343 1
                    eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2344 1
                    gate = null;
2345
                }
2346
            }
2347
            else
2348
            {
2349
                /* No gate, no prefix to append to.
2350
                 * Handle problem 2) by calling the copy constructor for value structs
2351
                 * (or static arrays of them) if appropriate.
2352
                 */
2353 1
                Type tv = arg.type.baseElemOf();
2354 1
                if (!isRef && tv.ty == Tstruct)
2355 1
                    arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2356
            }
2357

2358 1
            (*arguments)[i] = arg;
2359
        }
2360
    }
2361
    //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2362

2363
    /* Test compliance with DIP1021
2364
     */
2365 1
    if (global.params.useDIP1021 &&
2366 1
        tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2367 1
        err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2368

2369
    // If D linkage and variadic, add _arguments[] as first argument
2370 1
    if (tf.isDstyleVariadic())
2371
    {
2372 1
        assert(arguments.dim >= nparams);
2373

2374 1
        auto args = new Parameters(arguments.dim - nparams);
2375 1
        for (size_t i = 0; i < arguments.dim - nparams; i++)
2376
        {
2377 1
            auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2378 1
            (*args)[i] = arg;
2379
        }
2380 1
        auto tup = new TypeTuple(args);
2381 1
        Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2382 1
        arguments.insert(0, e);
2383
    }
2384

2385
    /* Determine function return type: tret
2386
     */
2387 1
    Type tret = tf.next;
2388 1
    if (isCtorCall)
2389
    {
2390
        //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2391
        //    wildmatch, tf.isWild(), fd.isReturnIsolated());
2392 1
        if (!tthis)
2393
        {
2394 0
            assert(sc.intypeof || global.errors);
2395 0
            tthis = fd.isThis().type.addMod(fd.type.mod);
2396
        }
2397 1
        if (tf.isWild() && !fd.isReturnIsolated())
2398
        {
2399 1
            if (wildmatch)
2400 1
                tret = tret.substWildTo(wildmatch);
2401 1
            int offset;
2402 1
            if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2403
            {
2404 1
                const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2405 1
                const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2406 1
                .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2407 1
                err = true;
2408
            }
2409
        }
2410 1
        tret = tthis;
2411
    }
2412 1
    else if (wildmatch && tret)
2413
    {
2414
        /* Adjust function return type based on wildmatch
2415
         */
2416
        //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2417 1
        tret = tret.substWildTo(wildmatch);
2418
    }
2419

2420 1
    *prettype = tret;
2421 1
    *peprefix = eprefix;
2422 1
    return (err || olderrors != global.errors);
2423
}
2424

2425
/**
2426
 * Determines whether a symbol represents a module or package
2427
 * (Used as a helper for is(type == module) and is(type == package))
2428
 *
2429
 * Params:
2430
 *  sym = the symbol to be checked
2431
 *
2432
 * Returns:
2433
 *  the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2434
 */
2435
Package resolveIsPackage(Dsymbol sym)
2436
{
2437 1
    Package pkg;
2438 1
    if (Import imp = sym.isImport())
2439
    {
2440 1
        if (imp.pkg is null)
2441
        {
2442 0
            .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
2443
                    imp.toChars());
2444 0
            assert(0);
2445
        }
2446 1
        pkg = imp.pkg;
2447
    }
2448 1
    else if (auto mod = sym.isModule())
2449 1
        pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2450
    else
2451 1
        pkg = sym.isPackage();
2452 1
    if (pkg)
2453 1
        pkg.resolvePKGunknown();
2454 1
    return pkg;
2455
}
2456

2457
private Module loadStdMath()
2458
{
2459 1
    __gshared Import impStdMath = null;
2460 1
    if (!impStdMath)
2461
    {
2462 1
        auto a = new Identifiers();
2463 1
        a.push(Id.std);
2464 1
        auto s = new Import(Loc.initial, a, Id.math, null, false);
2465
        // Module.load will call fatal() if there's no std.math available.
2466
        // Gag the error here, pushing the error handling to the caller.
2467 1
        uint errors = global.startGagging();
2468 1
        s.load(null);
2469 1
        if (s.mod)
2470
        {
2471 1
            s.mod.importAll(null);
2472 1
            s.mod.dsymbolSemantic(null);
2473
        }
2474 1
        global.endGagging(errors);
2475 1
        impStdMath = s;
2476
    }
2477 1
    return impStdMath.mod;
2478
}
2479

2480
private extern (C++) final class ExpressionSemanticVisitor : Visitor
2481
{
2482
    alias visit = Visitor.visit;
2483

2484
    Scope* sc;
2485
    Expression result;
2486

2487 1
    this(Scope* sc)
2488
    {
2489 1
        this.sc = sc;
2490
    }
2491

2492
    private void setError()
2493
    {
2494 1
        result = ErrorExp.get();
2495
    }
2496

2497
    /**************************
2498
     * Semantically analyze Expression.
2499
     * Determine types, fold constants, etc.
2500
     */
2501
    override void visit(Expression e)
2502
    {
2503
        static if (LOGSEMANTIC)
2504
        {
2505
            printf("Expression::semantic() %s\n", e.toChars());
2506
        }
2507 1
        if (e.type)
2508 1
            e.type = e.type.typeSemantic(e.loc, sc);
2509
        else
2510 1
            e.type = Type.tvoid;
2511 1
        result = e;
2512
    }
2513

2514
    override void visit(IntegerExp e)
2515
    {
2516 1
        assert(e.type);
2517 1
        if (e.type.ty == Terror)
2518 0
            return setError();
2519

2520 1
        assert(e.type.deco);
2521 1
        e.setInteger(e.getInteger());
2522 1
        result = e;
2523
    }
2524

2525
    override void visit(RealExp e)
2526
    {
2527 1
        if (!e.type)
2528 0
            e.type = Type.tfloat64;
2529
        else
2530 1
            e.type = e.type.typeSemantic(e.loc, sc);
2531 1
        result = e;
2532
    }
2533

2534
    override void visit(ComplexExp e)
2535
    {
2536 1
        if (!e.type)
2537 0
            e.type = Type.tcomplex80;
2538
        else
2539 1
            e.type = e.type.typeSemantic(e.loc, sc);
2540 1
        result = e;
2541
    }
2542

2543
    override void visit(IdentifierExp exp)
2544
    {
2545
        static if (LOGSEMANTIC)
2546
        {
2547
            printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2548
        }
2549 1
        if (exp.type) // This is used as the dummy expression
2550
        {
2551 0
            result = exp;
2552 0
            return;
2553
        }
2554

2555 1
        Dsymbol scopesym;
2556 1
        Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2557 1
        if (s)
2558
        {
2559 1
            if (s.errors)
2560 1
                return setError();
2561

2562 1
            Expression e;
2563

2564
            /* See if the symbol was a member of an enclosing 'with'
2565
             */
2566 1
            WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2567 1
            if (withsym && withsym.withstate.wthis)
2568
            {
2569
                /* Disallow shadowing
2570
                 */
2571
                // First find the scope of the with
2572 1
                Scope* scwith = sc;
2573 1
                while (scwith.scopesym != scopesym)
2574
                {
2575 1
                    scwith = scwith.enclosing;
2576 1
                    assert(scwith);
2577
                }
2578
                // Look at enclosing scopes for symbols with the same name,
2579
                // in the same function
2580 1
                for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2581
                {
2582 1
                    Dsymbol s2;
2583 1
                    if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2584
                    {
2585 1
                        exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2586 1
                        return setError();
2587
                    }
2588
                }
2589 1
                s = s.toAlias();
2590

2591
                // Same as wthis.ident
2592
                //  TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2593
                //  The redudancy should be removed.
2594 1
                e = new VarExp(exp.loc, withsym.withstate.wthis);
2595 1
                e = new DotIdExp(exp.loc, e, exp.ident);
2596 1
                e = e.expressionSemantic(sc);
2597
            }
2598
            else
2599
            {
2600 1
                if (withsym)
2601
                {
2602 1
                    if (auto t = withsym.withstate.exp.isTypeExp())
2603
                    {
2604 1
                        e = new TypeExp(exp.loc, t.type);
2605 1
                        e = new DotIdExp(exp.loc, e, exp.ident);
2606 1
                        result = e.expressionSemantic(sc);
2607 1
                        return;
2608
                    }
2609
                }
2610

2611
                /* If f is really a function template,
2612
                 * then replace f with the function template declaration.
2613
                 */
2614 1
                FuncDeclaration f = s.isFuncDeclaration();
2615 1
                if (f)
2616
                {
2617 1
                    TemplateDeclaration td = getFuncTemplateDecl(f);
2618 1
                    if (td)
2619
                    {
2620 1
                        if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2621 1
                            td = td.overroot; // then get the start
2622 1
                        e = new TemplateExp(exp.loc, td, f);
2623 1
                        e = e.expressionSemantic(sc);
2624 1
                        result = e;
2625 1
                        return;
2626
                    }
2627
                }
2628

2629 1
                if (global.params.fixAliasThis)
2630
                {
2631 1
                    ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2632 1
                    if (expDsym)
2633
                    {
2634
                        //printf("expDsym = %s\n", expDsym.exp.toChars());
2635 1
                        result = expDsym.exp.expressionSemantic(sc);
2636 1
                        return;
2637
                    }
2638
                }
2639
                // Haven't done overload resolution yet, so pass 1
2640 1
                e = symbolToExp(s, exp.loc, sc, true);
2641
            }
2642 1
            result = e;
2643 1
            return;
2644
        }
2645

2646 1
        if (!global.params.fixAliasThis && hasThis(sc))
2647
        {
2648 1
            for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2649
            {
2650 1
                if (ad.aliasthis)
2651
                {
2652 1
                    Expression e;
2653 1
                    e = new ThisExp(exp.loc);
2654 1
                    e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2655 1
                    e = new DotIdExp(exp.loc, e, exp.ident);
2656 1
                    e = e.trySemantic(sc);
2657 1
                    if (e)
2658
                    {
2659 1
                        result = e;
2660 1
                        return;
2661
                    }
2662
                }
2663

2664 1
                auto cd = ad.isClassDeclaration();
2665 1
                if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2666
                {
2667 1
                    ad = cd.baseClass;
2668 1
                    continue;
2669
                }
2670 1
                break;
2671
            }
2672
        }
2673

2674 1
        if (exp.ident == Id.ctfe)
2675
        {
2676 1
            if (sc.flags & SCOPE.ctfe)
2677
            {
2678 1
                exp.error("variable `__ctfe` cannot be read at compile time");
2679 1
                return setError();
2680
            }
2681

2682
            // Create the magic __ctfe bool variable
2683 1
            auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2684 1
            vd.storage_class |= STC.temp;
2685 1
            vd.semanticRun = PASS.semanticdone;
2686 1
            Expression e = new VarExp(exp.loc, vd);
2687 1
            e = e.expressionSemantic(sc);
2688 1
            result = e;
2689 1
            return;
2690
        }
2691

2692
        // If we've reached this point and are inside a with() scope then we may
2693
        // try one last attempt by checking whether the 'wthis' object supports
2694
        // dynamic dispatching via opDispatch.
2695
        // This is done by rewriting this expression as wthis.ident.
2696
        // The innermost with() scope of the hierarchy to satisfy the condition
2697
        // above wins.
2698
        // https://issues.dlang.org/show_bug.cgi?id=6400
2699 1
        for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2700
        {
2701 1
            if (!sc2.scopesym)
2702 1
                continue;
2703

2704 1
            if (auto ss = sc2.scopesym.isWithScopeSymbol())
2705
            {
2706 1
                if (ss.withstate.wthis)
2707
                {
2708 1
                    Expression e;
2709 1
                    e = new VarExp(exp.loc, ss.withstate.wthis);
2710 1
                    e = new DotIdExp(exp.loc, e, exp.ident);
2711 1
                    e = e.trySemantic(sc);
2712 1
                    if (e)
2713
                    {
2714 1
                        result = e;
2715 1
                        return;
2716
                    }
2717
                }
2718
                // Try Type.opDispatch (so the static version)
2719 1
                else if (ss.withstate.exp && ss.withstate.exp.op == TOK.type)
2720
                {
2721 1
                    if (Type t = ss.withstate.exp.isTypeExp().type)
2722
                    {
2723 1
                        Expression e;
2724 1
                        e = new TypeExp(exp.loc, t);
2725 1
                        e = new DotIdExp(exp.loc, e, exp.ident);
2726 1
                        e = e.trySemantic(sc);
2727 1
                        if (e)
2728
                        {
2729 1
                            result = e;
2730 1
                            return;
2731
                        }
2732
                    }
2733
                }
2734
            }
2735
        }
2736

2737
        /* Look for what user might have meant
2738
         */
2739 1
        if (const n = importHint(exp.ident.toString()))
2740 1
            exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2741 1
        else if (auto s2 = sc.search_correct(exp.ident))
2742 1
            exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2743 1
        else if (const p = Scope.search_correct_C(exp.ident))
2744 1
            exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2745
        else
2746 1
            exp.error("undefined identifier `%s`", exp.ident.toChars());
2747

2748 1
        result = ErrorExp.get();
2749
    }
2750

2751
    override void visit(DsymbolExp e)
2752
    {
2753 1
        result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2754
    }
2755

2756
    override void visit(ThisExp e)
2757
    {
2758
        static if (LOGSEMANTIC)
2759
        {
2760
            printf("ThisExp::semantic()\n");
2761
        }
2762 1
        if (e.type)
2763
        {
2764 1
            result = e;
2765 1
            return;
2766
        }
2767

2768 1
        FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2769 1
        AggregateDeclaration ad;
2770

2771
        /* Special case for typeof(this) and typeof(super) since both
2772
         * should work even if they are not inside a non-static member function
2773
         */
2774 1
        if (!fd && sc.intypeof == 1)
2775
        {
2776
            // Find enclosing struct or class
2777 1
            for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2778
            {
2779 1
                if (!s)
2780
                {
2781 0
                    e.error("`%s` is not in a class or struct scope", e.toChars());
2782 0
                    goto Lerr;
2783
                }
2784 1
                ClassDeclaration cd = s.isClassDeclaration();
2785 1
                if (cd)
2786
                {
2787 1
                    e.type = cd.type;
2788 1
                    result = e;
2789 1
                    return;
2790
                }
2791 1
                StructDeclaration sd = s.isStructDeclaration();
2792 1
                if (sd)
2793
                {
2794 1
                    e.type = sd.type;
2795 1
                    result = e;
2796 1
                    return;
2797
                }
2798
            }
2799
        }
2800 1
        if (!fd)
2801 1
            goto Lerr;
2802

2803 1
        assert(fd.vthis);
2804 1
        e.var = fd.vthis;
2805 1
        assert(e.var.parent);
2806 1
        ad = fd.isMemberLocal();
2807 1
        if (!ad)
2808 1
            ad = fd.isMember2();
2809 1
        assert(ad);
2810 1
        e.type = ad.type.addMod(e.var.type.mod);
2811

2812 1