1
/**
2
 * Defines the bulk of the classes which represent the AST at the expression level.
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/expression.d, _expression.d)
10
 * Documentation:  https://dlang.org/phobos/dmd_expression.html
11
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expression.d
12
 */
13

14
module dmd.expression;
15

16
import core.stdc.stdarg;
17
import core.stdc.stdio;
18
import core.stdc.string;
19

20
import dmd.aggregate;
21
import dmd.aliasthis;
22
import dmd.apply;
23
import dmd.arrayop;
24
import dmd.arraytypes;
25
import dmd.ast_node;
26
import dmd.gluelayer;
27
import dmd.canthrow;
28
import dmd.complex;
29
import dmd.constfold;
30
import dmd.ctfeexpr;
31
import dmd.ctorflow;
32
import dmd.dcast;
33
import dmd.dclass;
34
import dmd.declaration;
35
import dmd.delegatize;
36
import dmd.dimport;
37
import dmd.dinterpret;
38
import dmd.dmodule;
39
import dmd.dscope;
40
import dmd.dstruct;
41
import dmd.dsymbol;
42
import dmd.dsymbolsem;
43
import dmd.dtemplate;
44
import dmd.errors;
45
import dmd.escape;
46
import dmd.expressionsem;
47
import dmd.func;
48
import dmd.globals;
49
import dmd.hdrgen;
50
import dmd.id;
51
import dmd.identifier;
52
import dmd.inline;
53
import dmd.mtype;
54
import dmd.nspace;
55
import dmd.objc;
56
import dmd.opover;
57
import dmd.optimize;
58
import dmd.root.ctfloat;
59
import dmd.root.filename;
60
import dmd.root.outbuffer;
61
import dmd.root.rmem;
62
import dmd.root.rootobject;
63
import dmd.root.string;
64
import dmd.safe;
65
import dmd.sideeffect;
66
import dmd.target;
67
import dmd.tokens;
68
import dmd.typesem;
69
import dmd.utf;
70
import dmd.visitor;
71

72
enum LOGSEMANTIC = false;
73
void emplaceExp(T : Expression, Args...)(void* p, Args args)
74
{
75 1
    scope tmp = new T(args);
76 1
    memcpy(p, cast(void*)tmp, __traits(classInstanceSize, T));
77
}
78

79
void emplaceExp(T : UnionExp)(T* p, Expression e)
80
{
81 1
    memcpy(p, cast(void*)e, e.size);
82
}
83

84
// Return value for `checkModifiable`
85
enum Modifiable
86
{
87
    /// Not modifiable
88
    no,
89
    /// Modifiable (the type is mutable)
90
    yes,
91
    /// Modifiable because it is initialization
92
    initialization,
93
}
94

95
/****************************************
96
 * Find the first non-comma expression.
97
 * Params:
98
 *      e = Expressions connected by commas
99
 * Returns:
100
 *      left-most non-comma expression
101
 */
102
inout(Expression) firstComma(inout Expression e)
103
{
104 1
    Expression ex = cast()e;
105 1
    while (ex.op == TOK.comma)
106 1
        ex = (cast(CommaExp)ex).e1;
107 1
    return cast(inout)ex;
108

109
}
110

111
/****************************************
112
 * Find the last non-comma expression.
113
 * Params:
114
 *      e = Expressions connected by commas
115
 * Returns:
116
 *      right-most non-comma expression
117
 */
118

119
inout(Expression) lastComma(inout Expression e)
120
{
121 1
    Expression ex = cast()e;
122 1
    while (ex.op == TOK.comma)
123 1
        ex = (cast(CommaExp)ex).e2;
124 1
    return cast(inout)ex;
125

126
}
127

128
/*****************************************
129
 * Determine if `this` is available by walking up the enclosing
130
 * scopes until a function is found.
131
 *
132
 * Params:
133
 *      sc = where to start looking for the enclosing function
134
 * Returns:
135
 *      Found function if it satisfies `isThis()`, otherwise `null`
136
 */
137
FuncDeclaration hasThis(Scope* sc)
138
{
139
    //printf("hasThis()\n");
140 1
    Dsymbol p = sc.parent;
141 1
    while (p && p.isTemplateMixin())
142 1
        p = p.parent;
143 1
    FuncDeclaration fdthis = p ? p.isFuncDeclaration() : null;
144
    //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis.toChars() : "");
145

146
    // Go upwards until we find the enclosing member function
147 1
    FuncDeclaration fd = fdthis;
148 1
    while (1)
149
    {
150 1
        if (!fd)
151
        {
152 1
            return null;
153
        }
154 1
        if (!fd.isNested() || fd.isThis() || (fd.isThis2 && fd.isMember2()))
155 1
            break;
156

157 1
        Dsymbol parent = fd.parent;
158 1
        while (1)
159
        {
160 1
            if (!parent)
161 0
                return null;
162 1
            TemplateInstance ti = parent.isTemplateInstance();
163 1
            if (ti)
164 1
                parent = ti.parent;
165
            else
166 1
                break;
167
        }
168 1
        fd = parent.isFuncDeclaration();
169
    }
170

171 1
    if (!fd.isThis() && !(fd.isThis2 && fd.isMember2()))
172
    {
173 1
        return null;
174
    }
175

176 1
    assert(fd.vthis);
177 1
    return fd;
178

179
}
180

181
/***********************************
182
 * Determine if a `this` is needed to access `d`.
183
 * Params:
184
 *      sc = context
185
 *      d = declaration to check
186
 * Returns:
187
 *      true means a `this` is needed
188
 */
189
bool isNeedThisScope(Scope* sc, Declaration d)
190
{
191 1
    if (sc.intypeof == 1)
192 1
        return false;
193

194 1
    AggregateDeclaration ad = d.isThis();
195 1
    if (!ad)
196 1
        return false;
197
    //printf("d = %s, ad = %s\n", d.toChars(), ad.toChars());
198

199 1
    for (Dsymbol s = sc.parent; s; s = s.toParentLocal())
200
    {
201
        //printf("\ts = %s %s, toParent2() = %p\n", s.kind(), s.toChars(), s.toParent2());
202 1
        if (AggregateDeclaration ad2 = s.isAggregateDeclaration())
203
        {
204 1
            if (ad2 == ad)
205 1
                return false;
206 1
            else if (ad2.isNested())
207 0
                continue;
208
            else
209 1
                return true;
210
        }
211 1
        if (FuncDeclaration f = s.isFuncDeclaration())
212
        {
213 1
            if (f.isMemberLocal())
214 1
                break;
215
        }
216
    }
217 1
    return true;
218
}
219

220
/******************************
221
 * check e is exp.opDispatch!(tiargs) or not
222
 * It's used to switch to UFCS the semantic analysis path
223
 */
224
bool isDotOpDispatch(Expression e)
225
{
226 1
    if (auto dtie = e.isDotTemplateInstanceExp())
227 1
        return dtie.ti.name == Id.opDispatch;
228 1
    return false;
229
}
230

231
/****************************************
232
 * Expand tuples.
233
 * Input:
234
 *      exps    aray of Expressions
235
 * Output:
236
 *      exps    rewritten in place
237
 */
238
extern (C++) void expandTuples(Expressions* exps)
239
{
240
    //printf("expandTuples()\n");
241 1
    if (exps is null)
242 0
        return;
243

244 1
    for (size_t i = 0; i < exps.dim; i++)
245
    {
246 1
        Expression arg = (*exps)[i];
247 1
        if (!arg)
248 1
            continue;
249

250
        // Look for tuple with 0 members
251 1
        if (auto e = arg.isTypeExp())
252
        {
253 1
            if (auto tt = e.type.toBasetype().isTypeTuple())
254
            {
255 1
                if (!tt.arguments || tt.arguments.dim == 0)
256
                {
257 1
                    exps.remove(i);
258 1
                    if (i == exps.dim)
259 1
                        return;
260
                }
261
                else // Expand a TypeTuple
262
                {
263 1
                    exps.remove(i);
264 1
                    auto texps = new Expressions(tt.arguments.length);
265 1
                    foreach (j, a; *tt.arguments)
266 1
                        (*texps)[j] = new TypeExp(e.loc, a.type);
267 1
                    exps.insert(i, texps);
268
                }
269 1
                i--;
270 1
                continue;
271
            }
272
        }
273

274
        // Inline expand all the tuples
275 1
        while (arg.op == TOK.tuple)
276
        {
277 1
            TupleExp te = cast(TupleExp)arg;
278 1
            exps.remove(i); // remove arg
279 1
            exps.insert(i, te.exps); // replace with tuple contents
280 1
            if (i == exps.dim)
281 1
                return; // empty tuple, no more arguments
282 1
            (*exps)[i] = Expression.combine(te.e0, (*exps)[i]);
283 1
            arg = (*exps)[i];
284
        }
285
    }
286
}
287

288
/****************************************
289
 * Expand alias this tuples.
290
 */
291
TupleDeclaration isAliasThisTuple(Expression e)
292
{
293 1
    if (!e.type)
294 0
        return null;
295

296 1
    Type t = e.type.toBasetype();
297 1
    while (true)
298
    {
299 1
        if (Dsymbol s = t.toDsymbol(null))
300
        {
301 1
            if (auto ad = s.isAggregateDeclaration())
302
            {
303 1
                s = ad.aliasthis ? ad.aliasthis.sym : null;
304 1
                if (s && s.isVarDeclaration())
305
                {
306 1
                    TupleDeclaration td = s.isVarDeclaration().toAlias().isTupleDeclaration();
307 1
                    if (td && td.isexp)
308 1
                        return td;
309
                }
310 1
                if (Type att = t.aliasthisOf())
311
                {
312 1
                    t = att;
313 1
                    continue;
314
                }
315
            }
316
        }
317 1
        return null;
318
    }
319
}
320

321
int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
322
{
323 1
    if (!exps || exps.dim == 0)
324 0
        return -1;
325

326 1
    for (size_t u = starti; u < exps.dim; u++)
327
    {
328 1
        Expression exp = (*exps)[u];
329 1
        if (TupleDeclaration td = exp.isAliasThisTuple)
330
        {
331 1
            exps.remove(u);
332 1
            foreach (i, o; *td.objects)
333
            {
334 1
                auto d = o.isExpression().isDsymbolExp().s.isDeclaration();
335 1
                auto e = new DotVarExp(exp.loc, exp, d);
336 1
                assert(d.type);
337 1
                e.type = d.type;
338 1
                exps.insert(u + i, e);
339
            }
340
            version (none)
341
            {
342
                printf("expansion ->\n");
343
                foreach (e; exps)
344
                {
345
                    printf("\texps[%d] e = %s %s\n", i, Token.tochars[e.op], e.toChars());
346
                }
347
            }
348 1
            return cast(int)u;
349
        }
350
    }
351 1
    return -1;
352
}
353

354
/****************************************
355
 * If `s` is a function template, i.e. the only member of a template
356
 * and that member is a function, return that template.
357
 * Params:
358
 *      s = symbol that might be a function template
359
 * Returns:
360
 *      template for that function, otherwise null
361
 */
362
TemplateDeclaration getFuncTemplateDecl(Dsymbol s)
363
{
364 1
    FuncDeclaration f = s.isFuncDeclaration();
365 1
    if (f && f.parent)
366
    {
367 1
        if (auto ti = f.parent.isTemplateInstance())
368
        {
369 1
            if (!ti.isTemplateMixin() && ti.tempdecl)
370
            {
371 1
                auto td = ti.tempdecl.isTemplateDeclaration();
372 1
                if (td.onemember && td.ident == f.ident)
373
                {
374 1
                    return td;
375
                }
376
            }
377
        }
378
    }
379 1
    return null;
380
}
381

382
/************************************************
383
 * If we want the value of this expression, but do not want to call
384
 * the destructor on it.
385
 */
386
Expression valueNoDtor(Expression e)
387
{
388 1
    auto ex = lastComma(e);
389

390 1
    if (auto ce = ex.isCallExp())
391
    {
392
        /* The struct value returned from the function is transferred
393
         * so do not call the destructor on it.
394
         * Recognize:
395
         *       ((S _ctmp = S.init), _ctmp).this(...)
396
         * and make sure the destructor is not called on _ctmp
397
         * BUG: if ex is a CommaExp, we should go down the right side.
398
         */
399 1
        if (auto dve = ce.e1.isDotVarExp())
400
        {
401 1
            if (dve.var.isCtorDeclaration())
402
            {
403
                // It's a constructor call
404 1
                if (auto comma = dve.e1.isCommaExp())
405
                {
406 1
                    if (auto ve = comma.e2.isVarExp())
407
                    {
408 1
                        VarDeclaration ctmp = ve.var.isVarDeclaration();
409 1
                        if (ctmp)
410
                        {
411 1
                            ctmp.storage_class |= STC.nodtor;
412 1
                            assert(!ce.isLvalue());
413
                        }
414
                    }
415
                }
416
            }
417
        }
418
    }
419 1
    else if (auto ve = ex.isVarExp())
420
    {
421 1
        auto vtmp = ve.var.isVarDeclaration();
422 1
        if (vtmp && (vtmp.storage_class & STC.rvalue))
423
        {
424 1
            vtmp.storage_class |= STC.nodtor;
425
        }
426
    }
427 1
    return e;
428
}
429

430
/*********************************************
431
 * If e is an instance of a struct, and that struct has a copy constructor,
432
 * rewrite e as:
433
 *    (tmp = e),tmp
434
 * Input:
435
 *      sc = just used to specify the scope of created temporary variable
436
 *      destinationType = the type of the object on which the copy constructor is called;
437
 *                        may be null if the struct defines a postblit
438
 */
439
private Expression callCpCtor(Scope* sc, Expression e, Type destinationType)
440
{
441 1
    if (auto ts = e.type.baseElemOf().isTypeStruct())
442
    {
443 1
        StructDeclaration sd = ts.sym;
444 1
        if (sd.postblit || sd.hasCopyCtor)
445
        {
446
            /* Create a variable tmp, and replace the argument e with:
447
             *      (tmp = e),tmp
448
             * and let AssignExp() handle the construction.
449
             * This is not the most efficient, ideally tmp would be constructed
450
             * directly onto the stack.
451
             */
452 1
            auto tmp = copyToTemp(STC.rvalue, "__copytmp", e);
453 1
            if (sd.hasCopyCtor && destinationType)
454 1
                tmp.type = destinationType;
455 1
            tmp.storage_class |= STC.nodtor;
456 1
            tmp.dsymbolSemantic(sc);
457 1
            Expression de = new DeclarationExp(e.loc, tmp);
458 1
            Expression ve = new VarExp(e.loc, tmp);
459 1
            de.type = Type.tvoid;
460 1
            ve.type = e.type;
461 1
            return Expression.combine(de, ve);
462
        }
463
    }
464 1
    return e;
465
}
466

467
/************************************************
468
 * Handle the postblit call on lvalue, or the move of rvalue.
469
 *
470
 * Params:
471
 *   sc = the scope where the expression is encountered
472
 *   e = the expression the needs to be moved or copied (source)
473
 *   t = if the struct defines a copy constructor, the type of the destination
474
 *
475
 * Returns:
476
 *  The expression that copy constructs or moves the value.
477
 */
478
extern (D) Expression doCopyOrMove(Scope *sc, Expression e, Type t = null)
479
{
480 1
    if (auto ce = e.isCondExp())
481
    {
482 1
        ce.e1 = doCopyOrMove(sc, ce.e1);
483 1
        ce.e2 = doCopyOrMove(sc, ce.e2);
484
    }
485
    else
486
    {
487 1
        e = e.isLvalue() ? callCpCtor(sc, e, t) : valueNoDtor(e);
488
    }
489 1
    return e;
490
}
491

492
/****************************************************************/
493
/* A type meant as a union of all the Expression types,
494
 * to serve essentially as a Variant that will sit on the stack
495
 * during CTFE to reduce memory consumption.
496
 */
497
extern (C++) struct UnionExp
498
{
499
    // yes, default constructor does nothing
500 0
    extern (D) this(Expression e)
501
    {
502 0
        memcpy(&this, cast(void*)e, e.size);
503
    }
504

505
    /* Extract pointer to Expression
506
     */
507
    extern (C++) Expression exp() return
508
    {
509 1
        return cast(Expression)&u;
510
    }
511

512
    /* Convert to an allocated Expression
513
     */
514
    extern (C++) Expression copy()
515
    {
516 1
        Expression e = exp();
517
        //if (e.size > sizeof(u)) printf("%s\n", Token::toChars(e.op));
518 1
        assert(e.size <= u.sizeof);
519 1
        switch (e.op)
520
        {
521 1
            case TOK.cantExpression:    return CTFEExp.cantexp;
522 0
            case TOK.voidExpression:    return CTFEExp.voidexp;
523 0
            case TOK.break_:            return CTFEExp.breakexp;
524 0
            case TOK.continue_:         return CTFEExp.continueexp;
525 0
            case TOK.goto_:             return CTFEExp.gotoexp;
526 1
            default:                    return e.copy();
527
        }
528
    }
529

530
private:
531
    // Ensure that the union is suitably aligned.
532
    align(8) union __AnonStruct__u
533
    {
534
        char[__traits(classInstanceSize, Expression)] exp;
535
        char[__traits(classInstanceSize, IntegerExp)] integerexp;
536
        char[__traits(classInstanceSize, ErrorExp)] errorexp;
537
        char[__traits(classInstanceSize, RealExp)] realexp;
538
        char[__traits(classInstanceSize, ComplexExp)] complexexp;
539
        char[__traits(classInstanceSize, SymOffExp)] symoffexp;
540
        char[__traits(classInstanceSize, StringExp)] stringexp;
541
        char[__traits(classInstanceSize, ArrayLiteralExp)] arrayliteralexp;
542
        char[__traits(classInstanceSize, AssocArrayLiteralExp)] assocarrayliteralexp;
543
        char[__traits(classInstanceSize, StructLiteralExp)] structliteralexp;
544
        char[__traits(classInstanceSize, NullExp)] nullexp;
545
        char[__traits(classInstanceSize, DotVarExp)] dotvarexp;
546
        char[__traits(classInstanceSize, AddrExp)] addrexp;
547
        char[__traits(classInstanceSize, IndexExp)] indexexp;
548
        char[__traits(classInstanceSize, SliceExp)] sliceexp;
549
        char[__traits(classInstanceSize, VectorExp)] vectorexp;
550
    }
551

552
    __AnonStruct__u u;
553
}
554

555
/********************************
556
 * Test to see if two reals are the same.
557
 * Regard NaN's as equivalent.
558
 * Regard +0 and -0 as different.
559
 * Params:
560
 *      x1 = first operand
561
 *      x2 = second operand
562
 * Returns:
563
 *      true if x1 is x2
564
 *      else false
565
 */
566
bool RealIdentical(real_t x1, real_t x2)
567
{
568 1
    return (CTFloat.isNaN(x1) && CTFloat.isNaN(x2)) || CTFloat.isIdentical(x1, x2);
569
}
570

571
/************************ TypeDotIdExp ************************************/
572
/* Things like:
573
 *      int.size
574
 *      foo.size
575
 *      (foo).size
576
 *      cast(foo).size
577
 */
578
DotIdExp typeDotIdExp(const ref Loc loc, Type type, Identifier ident)
579
{
580 1
    return new DotIdExp(loc, new TypeExp(loc, type), ident);
581
}
582

583
/***************************************************
584
 * Given an Expression, find the variable it really is.
585
 *
586
 * For example, `a[index]` is really `a`, and `s.f` is really `s`.
587
 * Params:
588
 *      e = Expression to look at
589
 * Returns:
590
 *      variable if there is one, null if not
591
 */
592
VarDeclaration expToVariable(Expression e)
593
{
594 1
    while (1)
595
    {
596 1
        switch (e.op)
597
        {
598 1
            case TOK.variable:
599 1
                return (cast(VarExp)e).var.isVarDeclaration();
600

601 1
            case TOK.dotVariable:
602 1
                e = (cast(DotVarExp)e).e1;
603 1
                continue;
604

605 1
            case TOK.index:
606
            {
607 1
                IndexExp ei = cast(IndexExp)e;
608 1
                e = ei.e1;
609 1
                Type ti = e.type.toBasetype();
610 1
                if (ti.ty == Tsarray)
611 1
                    continue;
612 1
                return null;
613
            }
614

615 0
            case TOK.slice:
616
            {
617 0
                SliceExp ei = cast(SliceExp)e;
618 0
                e = ei.e1;
619 0
                Type ti = e.type.toBasetype();
620 0
                if (ti.ty == Tsarray)
621 0
                    continue;
622 0
                return null;
623
            }
624

625 1
            case TOK.this_:
626 1
            case TOK.super_:
627 1
                return (cast(ThisExp)e).var.isVarDeclaration();
628

629 1
            default:
630 1
                return null;
631
        }
632
    }
633
}
634

635
enum OwnedBy : ubyte
636
{
637
    code,          // normal code expression in AST
638
    ctfe,          // value expression for CTFE
639
    cache,         // constant value cached for CTFE
640
}
641

642
enum WANTvalue  = 0;    // default
643
enum WANTexpand = 1;    // expand const/immutable variables if possible
644

645
/***********************************************************
646
 * http://dlang.org/spec/expression.html#expression
647
 */
648
extern (C++) abstract class Expression : ASTNode
649
{
650
    const TOK op;   // to minimize use of dynamic_cast
651
    ubyte size;     // # of bytes in Expression so we can copy() it
652
    ubyte parens;   // if this is a parenthesized expression
653
    Type type;      // !=null means that semantic() has been run
654
    Loc loc;        // file location
655

656 1
    extern (D) this(const ref Loc loc, TOK op, int size)
657
    {
658
        //printf("Expression::Expression(op = %d) this = %p\n", op, this);
659 1
        this.loc = loc;
660 1
        this.op = op;
661 1
        this.size = cast(ubyte)size;
662
    }
663

664
    static void _init()
665
    {
666 1
        CTFEExp.cantexp = new CTFEExp(TOK.cantExpression);
667 1
        CTFEExp.voidexp = new CTFEExp(TOK.voidExpression);
668 1
        CTFEExp.breakexp = new CTFEExp(TOK.break_);
669 1
        CTFEExp.continueexp = new CTFEExp(TOK.continue_);
670 1
        CTFEExp.gotoexp = new CTFEExp(TOK.goto_);
671 1
        CTFEExp.showcontext = new CTFEExp(TOK.showCtfeContext);
672
    }
673

674
    /**
675
     * Deinitializes the global state of the compiler.
676
     *
677
     * This can be used to restore the state set by `_init` to its original
678
     * state.
679
     */
680
    static void deinitialize()
681
    {
682 0
        CTFEExp.cantexp = CTFEExp.cantexp.init;
683 0
        CTFEExp.voidexp = CTFEExp.voidexp.init;
684 0
        CTFEExp.breakexp = CTFEExp.breakexp.init;
685 0
        CTFEExp.continueexp = CTFEExp.continueexp.init;
686 0
        CTFEExp.gotoexp = CTFEExp.gotoexp.init;
687 0
        CTFEExp.showcontext = CTFEExp.showcontext.init;
688
    }
689

690
    /*********************************
691
     * Does *not* do a deep copy.
692
     */
693
    final Expression copy()
694
    {
695 1
        Expression e;
696 1
        if (!size)
697
        {
698
            debug
699
            {
700 0
                fprintf(stderr, "No expression copy for: %s\n", toChars());
701 0
                printf("op = %d\n", op);
702
            }
703 0
            assert(0);
704
        }
705

706
        // memory never freed, so can use the faster bump-pointer-allocation
707 1
        e = cast(Expression)allocmemory(size);
708
        //printf("Expression::copy(op = %d) e = %p\n", op, e);
709 1
        return cast(Expression)memcpy(cast(void*)e, cast(void*)this, size);
710
    }
711

712
    Expression syntaxCopy()
713
    {
714
        //printf("Expression::syntaxCopy()\n");
715
        //print();
716 1
        return copy();
717
    }
718

719
    // kludge for template.isExpression()
720
    override final DYNCAST dyncast() const
721
    {
722 1
        return DYNCAST.expression;
723
    }
724

725
    override const(char)* toChars() const
726
    {
727 1
        OutBuffer buf;
728 1
        HdrGenState hgs;
729 1
        toCBuffer(this, &buf, &hgs);
730 1
        return buf.extractChars();
731
    }
732

733
    final void error(const(char)* format, ...) const
734
    {
735 1
        if (type != Type.terror)
736
        {
737 1
            va_list ap;
738 1
            va_start(ap, format);
739 1
            .verror(loc, format, ap);
740 1
            va_end(ap);
741
        }
742
    }
743

744
    final void errorSupplemental(const(char)* format, ...)
745
    {
746 1
        if (type == Type.terror)
747 0
            return;
748

749 1
        va_list ap;
750 1
        va_start(ap, format);
751 1
        .verrorSupplemental(loc, format, ap);
752 1
        va_end(ap);
753
    }
754

755
    final void warning(const(char)* format, ...) const
756
    {
757 1
        if (type != Type.terror)
758
        {
759 1
            va_list ap;
760 1
            va_start(ap, format);
761 1
            .vwarning(loc, format, ap);
762 1
            va_end(ap);
763
        }
764
    }
765

766
    final void deprecation(const(char)* format, ...) const
767
    {
768 1
        if (type != Type.terror)
769
        {
770 1
            va_list ap;
771 1
            va_start(ap, format);
772 1
            .vdeprecation(loc, format, ap);
773 1
            va_end(ap);
774
        }
775
    }
776

777
    /**********************************
778
     * Combine e1 and e2 by CommaExp if both are not NULL.
779
     */
780
    extern (D) static Expression combine(Expression e1, Expression e2)
781
    {
782 1
        if (e1)
783
        {
784 1
            if (e2)
785
            {
786 1
                e1 = new CommaExp(e1.loc, e1, e2);
787 1
                e1.type = e2.type;
788
            }
789
        }
790
        else
791 1
            e1 = e2;
792 1
        return e1;
793
    }
794

795
    extern (D) static Expression combine(Expression e1, Expression e2, Expression e3)
796
    {
797 1
        return combine(combine(e1, e2), e3);
798
    }
799

800
    extern (D) static Expression combine(Expression e1, Expression e2, Expression e3, Expression e4)
801
    {
802 1
        return combine(combine(e1, e2), combine(e3, e4));
803
    }
804

805
    /**********************************
806
     * If 'e' is a tree of commas, returns the rightmost expression
807
     * by stripping off it from the tree. The remained part of the tree
808
     * is returned via e0.
809
     * Otherwise 'e' is directly returned and e0 is set to NULL.
810
     */
811
    extern (D) static Expression extractLast(Expression e, out Expression e0)
812
    {
813 1
        if (e.op != TOK.comma)
814
        {
815 1
            return e;
816
        }
817

818 1
        CommaExp ce = cast(CommaExp)e;
819 1
        if (ce.e2.op != TOK.comma)
820
        {
821 1
            e0 = ce.e1;
822 1
            return ce.e2;
823
        }
824
        else
825
        {
826 1
            e0 = e;
827

828 1
            Expression* pce = &ce.e2;
829 1
            while ((cast(CommaExp)(*pce)).e2.op == TOK.comma)
830
            {
831 0
                pce = &(cast(CommaExp)(*pce)).e2;
832
            }
833 1
            assert((*pce).op == TOK.comma);
834 1
            ce = cast(CommaExp)(*pce);
835 1
            *pce = ce.e1;
836

837 1
            return ce.e2;
838
        }
839
    }
840

841
    extern (D) static Expressions* arraySyntaxCopy(Expressions* exps)
842
    {
843 1
        Expressions* a = null;
844 1
        if (exps)
845
        {
846 1
            a = new Expressions(exps.dim);
847 1
            foreach (i, e; *exps)
848
            {
849 1
                (*a)[i] = e ? e.syntaxCopy() : null;
850
            }
851
        }
852 1
        return a;
853
    }
854

855
    dinteger_t toInteger()
856
    {
857
        //printf("Expression %s\n", Token::toChars(op));
858 1
        error("integer constant expression expected instead of `%s`", toChars());
859 1
        return 0;
860
    }
861

862
    uinteger_t toUInteger()
863
    {
864
        //printf("Expression %s\n", Token::toChars(op));
865 1
        return cast(uinteger_t)toInteger();
866
    }
867

868
    real_t toReal()
869
    {
870 0
        error("floating point constant expression expected instead of `%s`", toChars());
871 0
        return CTFloat.zero;
872
    }
873

874
    real_t toImaginary()
875
    {
876 0
        error("floating point constant expression expected instead of `%s`", toChars());
877 0
        return CTFloat.zero;
878
    }
879

880
    complex_t toComplex()
881
    {
882 0
        error("floating point constant expression expected instead of `%s`", toChars());
883 0
        return complex_t(CTFloat.zero);
884
    }
885

886
    StringExp toStringExp()
887
    {
888 1
        return null;
889
    }
890

891
    TupleExp toTupleExp()
892
    {
893 0
        return null;
894
    }
895

896
    /***************************************
897
     * Return !=0 if expression is an lvalue.
898
     */
899
    bool isLvalue()
900
    {
901 1
        return false;
902
    }
903

904
    /*******************************
905
     * Give error if we're not an lvalue.
906
     * If we can, convert expression to be an lvalue.
907
     */
908
    Expression toLvalue(Scope* sc, Expression e)
909
    {
910 1
        if (!e)
911 1
            e = this;
912 1
        else if (!loc.isValid())
913 0
            loc = e.loc;
914

915 1
        if (e.op == TOK.type)
916 1
            error("`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind());
917
        else
918 1
            error("`%s` is not an lvalue and cannot be modified", e.toChars());
919

920 1
        return ErrorExp.get();
921
    }
922

923
    Expression modifiableLvalue(Scope* sc, Expression e)
924
    {
925
        //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type.toChars());
926
        // See if this expression is a modifiable lvalue (i.e. not const)
927 1
        if (checkModifiable(sc) == Modifiable.yes)
928
        {
929 1
            assert(type);
930 1
            if (!type.isMutable())
931
            {
932 1
                if (auto dve = this.isDotVarExp())
933
                {
934 1
                    if (isNeedThisScope(sc, dve.var))
935 1
                        for (Dsymbol s = sc.func; s; s = s.toParentLocal())
936
                    {
937 1
                        FuncDeclaration ff = s.isFuncDeclaration();
938 1
                        if (!ff)
939 1
                            break;
940 1
                        if (!ff.type.isMutable)
941
                        {
942 1
                            error("cannot modify `%s` in `%s` function", toChars(), MODtoChars(type.mod));
943 1
                            return ErrorExp.get();
944
                        }
945
                    }
946
                }
947 1
                error("cannot modify `%s` expression `%s`", MODtoChars(type.mod), toChars());
948 1
                return ErrorExp.get();
949
            }
950 1
            else if (!type.isAssignable())
951
            {
952 1
                error("cannot modify struct instance `%s` of type `%s` because it contains `const` or `immutable` members",
953
                    toChars(), type.toChars());
954 1
                return ErrorExp.get();
955
            }
956
        }
957 1
        return toLvalue(sc, e);
958
    }
959

960
    final Expression implicitCastTo(Scope* sc, Type t)
961
    {
962 1
        return .implicitCastTo(this, sc, t);
963
    }
964

965
    final MATCH implicitConvTo(Type t)
966
    {
967 1
        return .implicitConvTo(this, t);
968
    }
969

970
    final Expression castTo(Scope* sc, Type t)
971
    {
972 1
        return .castTo(this, sc, t);
973
    }
974

975
    /****************************************
976
     * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, __FILE_FULL_PATH__ to loc.
977
     */
978
    Expression resolveLoc(const ref Loc loc, Scope* sc)
979
    {
980 1
        this.loc = loc;
981 1
        return this;
982
    }
983

984
    /****************************************
985
     * Check that the expression has a valid type.
986
     * If not, generates an error "... has no type".
987
     * Returns:
988
     *      true if the expression is not valid.
989
     * Note:
990
     *      When this function returns true, `checkValue()` should also return true.
991
     */
992
    bool checkType()
993
    {
994 1
        return false;
995
    }
996

997
    /****************************************
998
     * Check that the expression has a valid value.
999
     * If not, generates an error "... has no value".
1000
     * Returns:
1001
     *      true if the expression is not valid or has void type.
1002
     */
1003
    bool checkValue()
1004
    {
1005 1
        if (type && type.toBasetype().ty == Tvoid)
1006
        {
1007 1
            error("expression `%s` is `void` and has no value", toChars());
1008
            //print(); assert(0);
1009 1
            if (!global.gag)
1010 1
                type = Type.terror;
1011 1
            return true;
1012
        }
1013 1
        return false;
1014
    }
1015

1016
    extern (D) final bool checkScalar()
1017
    {
1018 1
        if (op == TOK.error)
1019 1
            return true;
1020 1
        if (type.toBasetype().ty == Terror)
1021 0
            return true;
1022 1
        if (!type.isscalar())
1023
        {
1024 1
            error("`%s` is not a scalar, it is a `%s`", toChars(), type.toChars());
1025 1
            return true;
1026
        }
1027 1
        return checkValue();
1028
    }
1029

1030
    extern (D) final bool checkNoBool()
1031
    {
1032 1
        if (op == TOK.error)
1033 0
            return true;
1034 1
        if (type.toBasetype().ty == Terror)
1035 0
            return true;
1036 1
        if (type.toBasetype().ty == Tbool)
1037
        {
1038 0
            error("operation not allowed on `bool` `%s`", toChars());
1039 0
            return true;
1040
        }
1041 1
        return false;
1042
    }
1043

1044
    extern (D) final bool checkIntegral()
1045
    {
1046 1
        if (op == TOK.error)
1047 0
            return true;
1048 1
        if (type.toBasetype().ty == Terror)
1049 0
            return true;
1050 1
        if (!type.isintegral())
1051
        {
1052 1
            error("`%s` is not of integral type, it is a `%s`", toChars(), type.toChars());
1053 1
            return true;
1054
        }
1055 1
        return checkValue();
1056
    }
1057

1058
    extern (D) final bool checkArithmetic()
1059
    {
1060 1
        if (op == TOK.error)
1061 0
            return true;
1062 1
        if (type.toBasetype().ty == Terror)
1063 0
            return true;
1064 1
        if (!type.isintegral() && !type.isfloating())
1065
        {
1066 1
            error("`%s` is not of arithmetic type, it is a `%s`", toChars(), type.toChars());
1067 1
            return true;
1068
        }
1069 1
        return checkValue();
1070
    }
1071

1072
    final bool checkDeprecated(Scope* sc, Dsymbol s)
1073
    {
1074 1
        return s.checkDeprecated(loc, sc);
1075
    }
1076

1077
    extern (D) final bool checkDisabled(Scope* sc, Dsymbol s)
1078
    {
1079 1
        if (auto d = s.isDeclaration())
1080
        {
1081 1
            return d.checkDisabled(loc, sc);
1082
        }
1083

1084 1
        return false;
1085
    }
1086

1087
    /*********************************************
1088
     * Calling function f.
1089
     * Check the purity, i.e. if we're in a pure function
1090
     * we can only call other pure functions.
1091
     * Returns true if error occurs.
1092
     */
1093
    extern (D) final bool checkPurity(Scope* sc, FuncDeclaration f)
1094
    {
1095 1
        if (!sc.func)
1096 1
            return false;
1097 1
        if (sc.func == f)
1098 1
            return false;
1099 1
        if (sc.intypeof == 1)
1100 1
            return false;
1101 1
        if (sc.flags & (SCOPE.ctfe | SCOPE.debug_))
1102 1
            return false;
1103

1104
        // If the call has a pure parent, then the called func must be pure.
1105 1
        if (!f.isPure() && checkImpure(sc))
1106
        {
1107 1
            error("`pure` %s `%s` cannot call impure %s `%s`",
1108
                sc.func.kind(), sc.func.toPrettyChars(), f.kind(),
1109
                f.toPrettyChars());
1110 1
            return true;
1111
        }
1112 1
        return false;
1113
    }
1114

1115
    /*******************************************
1116
     * Accessing variable v.
1117
     * Check for purity and safety violations.
1118
     * Returns true if error occurs.
1119
     */
1120
    extern (D) final bool checkPurity(Scope* sc, VarDeclaration v)
1121
    {
1122
        //printf("v = %s %s\n", v.type.toChars(), v.toChars());
1123
        /* Look for purity and safety violations when accessing variable v
1124
         * from current function.
1125
         */
1126 1
        if (!sc.func)
1127 1
            return false;
1128 1
        if (sc.intypeof == 1)
1129 1
            return false; // allow violations inside typeof(expression)
1130 1
        if (sc.flags & (SCOPE.ctfe | SCOPE.debug_))
1131 1
            return false; // allow violations inside compile-time evaluated expressions and debug conditionals
1132 1
        if (v.ident == Id.ctfe)
1133 1
            return false; // magic variable never violates pure and safe
1134 1
        if (v.isImmutable())
1135 1
            return false; // always safe and pure to access immutables...
1136 1
        if (v.isConst() && !v.isRef() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf()))
1137 1
            return false; // or const global/parameter values which have no mutable indirections
1138 1
        if (v.storage_class & STC.manifest)
1139 1
            return false; // ...or manifest constants
1140

1141 1
        if (v.type.ty == Tstruct)
1142
        {
1143 1
            StructDeclaration sd = (cast(TypeStruct)v.type).sym;
1144 1
            if (sd.hasNoFields)
1145 1
                return false;
1146
        }
1147

1148 1
        bool err = false;
1149 1
        if (v.isDataseg())
1150
        {
1151
            // https://issues.dlang.org/show_bug.cgi?id=7533
1152
            // Accessing implicit generated __gate is pure.
1153 1
            if (v.ident == Id.gate)
1154 1
                return false;
1155

1156 1
            if (checkImpure(sc))
1157
            {
1158 1
                error("`pure` %s `%s` cannot access mutable static data `%s`",
1159
                    sc.func.kind(), sc.func.toPrettyChars(), v.toChars());
1160 1
                err = true;
1161
            }
1162
        }
1163
        else
1164
        {
1165
            /* Given:
1166
             * void f() {
1167
             *   int fx;
1168
             *   pure void g() {
1169
             *     int gx;
1170
             *     /+pure+/ void h() {
1171
             *       int hx;
1172
             *       /+pure+/ void i() { }
1173
             *     }
1174
             *   }
1175
             * }
1176
             * i() can modify hx and gx but not fx
1177
             */
1178

1179 1
            Dsymbol vparent = v.toParent2();
1180 1
            for (Dsymbol s = sc.func; !err && s; s = s.toParentP(vparent))
1181
            {
1182 1
                if (s == vparent)
1183 1
                    break;
1184

1185 1
                if (AggregateDeclaration ad = s.isAggregateDeclaration())
1186
                {
1187 1
                    if (ad.isNested())
1188 1
                        continue;
1189 1
                    break;
1190
                }
1191 1
                FuncDeclaration ff = s.isFuncDeclaration();
1192 1
                if (!ff)
1193 1
                    break;
1194 1
                if (ff.isNested() || ff.isThis())
1195
                {
1196 1
                    if (ff.type.isImmutable() ||
1197 1
                        ff.type.isShared() && !MODimplicitConv(ff.type.mod, v.type.mod))
1198
                    {
1199 1
                        OutBuffer ffbuf;
1200 1
                        OutBuffer vbuf;
1201 1
                        MODMatchToBuffer(&ffbuf, ff.type.mod, v.type.mod);
1202 1
                        MODMatchToBuffer(&vbuf, v.type.mod, ff.type.mod);
1203 1
                        error("%s%s `%s` cannot access %sdata `%s`",
1204
                            ffbuf.peekChars(), ff.kind(), ff.toPrettyChars(), vbuf.peekChars(), v.toChars());
1205 1
                        err = true;
1206 1
                        break;
1207
                    }
1208 1
                    continue;
1209
                }
1210 1
                break;
1211
            }
1212
        }
1213

1214
        /* Do not allow safe functions to access __gshared data
1215
         */
1216 1
        if (v.storage_class & STC.gshared)
1217
        {
1218 1
            if (sc.func.setUnsafe())
1219
            {
1220 1
                error("`@safe` %s `%s` cannot access `__gshared` data `%s`",
1221
                    sc.func.kind(), sc.func.toChars(), v.toChars());
1222 1
                err = true;
1223
            }
1224
        }
1225

1226 1
        return err;
1227
    }
1228

1229
    /*
1230
    Check if sc.func is impure or can be made impure.
1231
    Returns true on error, i.e. if sc.func is pure and cannot be made impure.
1232
    */
1233
    private static bool checkImpure(Scope* sc)
1234
    {
1235 1
        return sc.func && (sc.flags & SCOPE.compile
1236 1
                ? sc.func.isPureBypassingInference() >= PURE.weak
1237 1
                : sc.func.setImpure());
1238
    }
1239

1240
    /*********************************************
1241
     * Calling function f.
1242
     * Check the safety, i.e. if we're in a @safe function
1243
     * we can only call @safe or @trusted functions.
1244
     * Returns true if error occurs.
1245
     */
1246
    extern (D) final bool checkSafety(Scope* sc, FuncDeclaration f)
1247
    {
1248 1
        if (!sc.func)
1249 1
            return false;
1250 1
        if (sc.func == f)
1251 1
            return false;
1252 1
        if (sc.intypeof == 1)
1253 1
            return false;
1254 1
        if (sc.flags & (SCOPE.ctfe | SCOPE.debug_))
1255 1
            return false;
1256

1257 1
        if (!f.isSafe() && !f.isTrusted())
1258
        {
1259 1
            if (sc.flags & SCOPE.compile ? sc.func.isSafeBypassingInference() : sc.func.setUnsafe())
1260
            {
1261 1
                if (!loc.isValid()) // e.g. implicitly generated dtor
1262 1
                    loc = sc.func.loc;
1263

1264 1
                const prettyChars = f.toPrettyChars();
1265 1
                error("`@safe` %s `%s` cannot call `@system` %s `%s`",
1266
                    sc.func.kind(), sc.func.toPrettyChars(), f.kind(),
1267
                    prettyChars);
1268 1
                .errorSupplemental(f.loc, "`%s` is declared here", prettyChars);
1269 1
                return true;
1270
            }
1271
        }
1272 1
        return false;
1273
    }
1274

1275
    /*********************************************
1276
     * Calling function f.
1277
     * Check the @nogc-ness, i.e. if we're in a @nogc function
1278
     * we can only call other @nogc functions.
1279
     * Returns true if error occurs.
1280
     */
1281
    extern (D) final bool checkNogc(Scope* sc, FuncDeclaration f)
1282
    {
1283 1
        if (!sc.func)
1284 1
            return false;
1285 1
        if (sc.func == f)
1286 1
            return false;
1287 1
        if (sc.intypeof == 1)
1288 1
            return false;
1289 1
        if (sc.flags & (SCOPE.ctfe | SCOPE.debug_))
1290 1
            return false;
1291

1292 1
        if (!f.isNogc())
1293
        {
1294 1
            if (sc.flags & SCOPE.compile ? sc.func.isNogcBypassingInference() : sc.func.setGC())
1295
            {
1296 1
                if (loc.linnum == 0) // e.g. implicitly generated dtor
1297 1
                    loc = sc.func.loc;
1298

1299
                // Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)),
1300
                // so don't print anything to avoid double error messages.
1301 1
                if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT))
1302 1
                    error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
1303
                        sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars());
1304 1
                return true;
1305
            }
1306
        }
1307 1
        return false;
1308
    }
1309

1310
    /********************************************
1311
     * Check that the postblit is callable if t is an array of structs.
1312
     * Returns true if error happens.
1313
     */
1314
    extern (D) final bool checkPostblit(Scope* sc, Type t)
1315
    {
1316 1
        if (auto ts = t.baseElemOf().isTypeStruct())
1317
        {
1318 1
            if (global.params.useTypeInfo)
1319
            {
1320
                // https://issues.dlang.org/show_bug.cgi?id=11395
1321
                // Require TypeInfo generation for array concatenation
1322 1
                semanticTypeInfo(sc, t);
1323
            }
1324

1325 1
            StructDeclaration sd = ts.sym;
1326 1
            if (sd.postblit)
1327
            {
1328 1
                if (sd.postblit.checkDisabled(loc, sc))
1329 1
                    return true;
1330

1331
                //checkDeprecated(sc, sd.postblit);        // necessary?
1332 1
                checkPurity(sc, sd.postblit);
1333 1
                checkSafety(sc, sd.postblit);
1334 1
                checkNogc(sc, sd.postblit);
1335
                //checkAccess(sd, loc, sc, sd.postblit);   // necessary?
1336 1
                return false;
1337
            }
1338
        }
1339 1
        return false;
1340
    }
1341

1342
    extern (D) final bool checkRightThis(Scope* sc)
1343
    {
1344 1
        if (op == TOK.error)
1345 1
            return true;
1346 1
        if (op == TOK.variable && type.ty != Terror)
1347
        {
1348 1
            VarExp ve = cast(VarExp)this;
1349 1
            if (isNeedThisScope(sc, ve.var))
1350
            {
1351
                //printf("checkRightThis sc.intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
1352
                //        sc.intypeof, sc.getStructClassScope(), func, fdthis);
1353 1
                error("need `this` for `%s` of type `%s`", ve.var.toChars(), ve.var.type.toChars());
1354 1
                return true;
1355
            }
1356
        }
1357 1
        return false;
1358
    }
1359

1360
    /*******************************
1361
     * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
1362
     * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
1363
     * Returns true if error occurs.
1364
     */
1365
    extern (D) final bool checkReadModifyWrite(TOK rmwOp, Expression ex = null)
1366
    {
1367
        //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : "");
1368 1
        if (!type || !type.isShared() || type.isTypeStruct() || type.isTypeClass())
1369 1
            return false;
1370

1371
        // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
1372 1
        switch (rmwOp)
1373
        {
1374 1
        case TOK.plusPlus:
1375 1
        case TOK.prePlusPlus:
1376 1
            rmwOp = TOK.addAssign;
1377 1
            break;
1378 1
        case TOK.minusMinus:
1379 1
        case TOK.preMinusMinus:
1380 1
            rmwOp = TOK.minAssign;
1381 1
            break;
1382 1
        default:
1383 1
            break;
1384
        }
1385

1386 1
        error("read-modify-write operations are not allowed for `shared` variables");
1387 1
        errorSupplemental("Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
1388 1
                          Token.toChars(rmwOp), toChars(), ex ? ex.toChars() : "1");
1389 1
        return true;
1390
    }
1391

1392
    /***************************************
1393
     * Parameters:
1394
     *      sc:     scope
1395
     *      flag:   1: do not issue error message for invalid modification
1396
     * Returns:
1397
     *      Whether the type is modifiable
1398
     */
1399
    Modifiable checkModifiable(Scope* sc, int flag = 0)
1400
    {
1401 1
        return type ? Modifiable.yes : Modifiable.no; // default modifiable
1402
    }
1403

1404
    /*****************************
1405
     * If expression can be tested for true or false,
1406
     * returns the modified expression.
1407
     * Otherwise returns ErrorExp.
1408
     */
1409
    Expression toBoolean(Scope* sc)
1410
    {
1411
        // Default is 'yes' - do nothing
1412 1
        Expression e = this;
1413 1
        Type t = type;
1414 1
        Type tb = type.toBasetype();
1415 1
        Type att = null;
1416

1417 1
        while (1)
1418
        {
1419
            // Structs can be converted to bool using opCast(bool)()
1420 1
            if (auto ts = tb.isTypeStruct())
1421
            {
1422 1
                AggregateDeclaration ad = ts.sym;
1423
                /* Don't really need to check for opCast first, but by doing so we
1424
                 * get better error messages if it isn't there.
1425
                 */
1426 1
                if (Dsymbol fd = search_function(ad, Id._cast))
1427
                {
1428 1
                    e = new CastExp(loc, e, Type.tbool);
1429 1
                    e = e.expressionSemantic(sc);
1430 1
                    return e;
1431
                }
1432

1433
                // Forward to aliasthis.
1434 1
                if (ad.aliasthis && tb != att)
1435
                {
1436 1
                    if (!att && tb.checkAliasThisRec())
1437 1
                        att = tb;
1438 1
                    e = resolveAliasThis(sc, e);
1439 1
                    t = e.type;
1440 1
                    tb = e.type.toBasetype();
1441 1
                    continue;
1442
                }
1443
            }
1444 1
            break;
1445
        }
1446

1447 1
        if (!t.isBoolean())
1448
        {
1449 1
            if (tb != Type.terror)
1450 1
                error("expression `%s` of type `%s` does not have a boolean value", toChars(), t.toChars());
1451 1
            return ErrorExp.get();
1452
        }
1453 1
        return e;
1454
    }
1455

1456
    /************************************************
1457
     * Destructors are attached to VarDeclarations.
1458
     * Hence, if expression returns a temp that needs a destructor,
1459
     * make sure and create a VarDeclaration for that temp.
1460
     */
1461
    Expression addDtorHook(Scope* sc)
1462
    {
1463 1
        return this;
1464
    }
1465

1466
    /******************************
1467
     * Take address of expression.
1468
     */
1469
    final Expression addressOf()
1470
    {
1471
        //printf("Expression::addressOf()\n");
1472
        debug
1473
        {
1474 1
            assert(op == TOK.error || isLvalue());
1475
        }
1476 1
        Expression e = new AddrExp(loc, this, type.pointerTo());
1477 1
        return e;
1478
    }
1479

1480
    /******************************
1481
     * If this is a reference, dereference it.
1482
     */
1483
    final Expression deref()
1484
    {
1485
        //printf("Expression::deref()\n");
1486
        // type could be null if forward referencing an 'auto' variable
1487 1
        if (type)
1488 1
            if (auto tr = type.isTypeReference())
1489
            {
1490 0
                Expression e = new PtrExp(loc, this, tr.next);
1491 0
                return e;
1492
            }
1493 1
        return this;
1494
    }
1495

1496
    final Expression optimize(int result, bool keepLvalue = false)
1497
    {
1498 1
        return Expression_optimize(this, result, keepLvalue);
1499
    }
1500

1501
    // Entry point for CTFE.
1502
    // A compile-time result is required. Give an error if not possible
1503
    final Expression ctfeInterpret()
1504
    {
1505 1
        return .ctfeInterpret(this);
1506
    }
1507

1508
    final int isConst()
1509
    {
1510 1
        return .isConst(this);
1511
    }
1512

1513
    /********************************
1514
     * Does this expression statically evaluate to a boolean 'result' (true or false)?
1515
     */
1516
    bool isBool(bool result)
1517
    {
1518 1
        return false;
1519
    }
1520

1521
    bool hasCode()
1522
    {
1523 1
        return true;
1524
    }
1525

1526
    final pure inout nothrow @nogc
1527
    {
1528 1
        inout(IntegerExp)   isIntegerExp() { return op == TOK.int64 ? cast(typeof(return))this : null; }
1529 0
        inout(ErrorExp)     isErrorExp() { return op == TOK.error ? cast(typeof(return))this : null; }
1530 1
        inout(VoidInitExp)  isVoidInitExp() { return op == TOK.void_ ? cast(typeof(return))this : null; }
1531 1
        inout(RealExp)      isRealExp() { return op == TOK.float64 ? cast(typeof(return))this : null; }
1532 1
        inout(ComplexExp)   isComplexExp() { return op == TOK.complex80 ? cast(typeof(return))this : null; }
1533 0
        inout(IdentifierExp) isIdentifierExp() { return op == TOK.identifier ? cast(typeof(return))this : null; }
1534 0
        inout(DollarExp)    isDollarExp() { return op == TOK.dollar ? cast(typeof(return))this : null; }
1535 1
        inout(DsymbolExp)   isDsymbolExp() { return op == TOK.dSymbol ? cast(typeof(return))this : null; }
1536 1
        inout(ThisExp)      isThisExp() { return op == TOK.this_ ? cast(typeof(return))this : null; }
1537 0
        inout(SuperExp)     isSuperExp() { return op == TOK.super_ ? cast(typeof(return))this : null; }
1538 1
        inout(NullExp)      isNullExp() { return op == TOK.null_ ? cast(typeof(return))this : null; }
1539 1
        inout(StringExp)    isStringExp() { return op == TOK.string_ ? cast(typeof(return))this : null; }
1540 1
        inout(TupleExp)     isTupleExp() { return op == TOK.tuple ? cast(typeof(return))this : null; }
1541 1
        inout(ArrayLiteralExp) isArrayLiteralExp() { return op == TOK.arrayLiteral ? cast(typeof(return))this : null; }
1542 1
        inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == TOK.assocArrayLiteral ? cast(typeof(return))this : null; }
1543 1
        inout(StructLiteralExp) isStructLiteralExp() { return op == TOK.structLiteral ? cast(typeof(return))this : null; }
1544 1
        inout(TypeExp)      isTypeExp() { return op == TOK.type ? cast(typeof(return))this : null; }
1545 1
        inout(ScopeExp)     isScopeExp() { return op == TOK.scope_ ? cast(typeof(return))this : null; }
1546 1
        inout(TemplateExp)  isTemplateExp() { return op == TOK.template_ ? cast(typeof(return))this : null; }
1547 1
        inout(NewExp) isNewExp() { return op == TOK.new_ ? cast(typeof(return))this : null; }
1548 0
        inout(NewAnonClassExp) isNewAnonClassExp() { return op == TOK.newAnonymousClass ? cast(typeof(return))this : null; }
1549 1
        inout(SymOffExp)    isSymOffExp() { return op == TOK.symbolOffset ? cast(typeof(return))this : null; }
1550 1
        inout(VarExp)       isVarExp() { return op == TOK.variable ? cast(typeof(return))this : null; }
1551 1
        inout(OverExp)      isOverExp() { return op == TOK.overloadSet ? cast(typeof(return))this : null; }
1552 1
        inout(FuncExp)      isFuncExp() { return op == TOK.function_ ? cast(typeof(return))this : null; }
1553 1
        inout(DeclarationExp) isDeclarationExp() { return op == TOK.declaration ? cast(typeof(return))this : null; }
1554 1
        inout(TypeidExp)    isTypeidExp() { return op == TOK.typeid_ ? cast(typeof(return))this : null; }
1555 0
        inout(TraitsExp)    isTraitsExp() { return op == TOK.traits ? cast(typeof(return))this : null; }
1556 0
        inout(HaltExp)      isHaltExp() { return op == TOK.halt ? cast(typeof(return))this : null; }
1557 0
        inout(IsExp)        isExp() { return op == TOK.is_ ? cast(typeof(return))this : null; }
1558 1
        inout(CompileExp)   isCompileExp() { return op == TOK.mixin_ ? cast(typeof(return))this : null; }
1559 0
        inout(ImportExp)    isImportExp() { return op == TOK.import_ ? cast(typeof(return))this : null; }
1560 1
        inout(AssertExp)    isAssertExp() { return op == TOK.assert_ ? cast(typeof(return))this : null; }
1561 1
        inout(DotIdExp)     isDotIdExp() { return op == TOK.dotIdentifier ? cast(typeof(return))this : null; }
1562 1
        inout(DotTemplateExp) isDotTemplateExp() { return op == TOK.dotTemplateDeclaration ? cast(typeof(return))this : null; }
1563 1
        inout(DotVarExp)    isDotVarExp() { return op == TOK.dotVariable ? cast(typeof(return))this : null; }
1564 1
        inout(DotTemplateInstanceExp) isDotTemplateInstanceExp() { return op == TOK.dotTemplateInstance ? cast(typeof(return))this : null; }
1565 1
        inout(DelegateExp)  isDelegateExp() { return op == TOK.delegate_ ? cast(typeof(return))this : null; }
1566 1
        inout(DotTypeExp)   isDotTypeExp() { return op == TOK.dotType ? cast(typeof(return))this : null; }
1567 1
        inout(CallExp)      isCallExp() { return op == TOK.call ? cast(typeof(return))this : null; }
1568 1
        inout(AddrExp)      isAddrExp() { return op == TOK.address ? cast(typeof(return))this : null; }
1569 1
        inout(PtrExp)       isPtrExp() { return op == TOK.star ? cast(typeof(return))this : null; }
1570 0
        inout(NegExp)       isNegExp() { return op == TOK.negate ? cast(typeof(return))this : null; }
1571 0
        inout(UAddExp)      isUAddExp() { return op == TOK.uadd ? cast(typeof(return))this : null; }
1572 0
        inout(ComExp)       isComExp() { return op == TOK.tilde ? cast(typeof(return))this : null; }
1573 1
        inout(NotExp)       isNotExp() { return op == TOK.not ? cast(typeof(return))this : null; }
1574 0
        inout(DeleteExp)    isDeleteExp() { return op == TOK.delete_ ? cast(typeof(return))this : null; }
1575 1
        inout(CastExp)      isCastExp() { return op == TOK.cast_ ? cast(typeof(return))this : null; }
1576 1
        inout(VectorExp)    isVectorExp() { return op == TOK.vector ? cast(typeof(return))this : null; }
1577 0
        inout(VectorArrayExp) isVectorArrayExp() { return op == TOK.vectorArray ? cast(typeof(return))this : null; }
1578 1
        inout(SliceExp)     isSliceExp() { return op == TOK.slice ? cast(typeof(return))this : null; }
1579 1
        inout(ArrayLengthExp) isArrayLengthExp() { return op == TOK.arrayLength ? cast(typeof(return))this : null; }
1580 1
        inout(ArrayExp)     isArrayExp() { return op == TOK.array ? cast(typeof(return))this : null; }
1581 1
        inout(DotExp)       isDotExp() { return op == TOK.dot ? cast(typeof(return))this : null; }
1582 1
        inout(CommaExp)     isCommaExp() { return op == TOK.comma ? cast(typeof(return))this : null; }
1583 0
        inout(IntervalExp)  isIntervalExp() { return op == TOK.interval ? cast(typeof(return))this : null; }
1584 0
        inout(DelegatePtrExp)     isDelegatePtrExp() { return op == TOK.delegatePointer ? cast(typeof(return))this : null; }
1585 0
        inout(DelegateFuncptrExp) isDelegateFuncptrExp() { return op == TOK.delegateFunctionPointer ? cast(typeof(return))this : null; }
1586 1
        inout(IndexExp)     isIndexExp() { return op == TOK.index ? cast(typeof(return))this : null; }
1587 0
        inout(PostExp)      isPostExp()  { return (op == TOK.plusPlus || op == TOK.minusMinus) ? cast(typeof(return))this : null; }
1588 0
        inout(PreExp)       isPreExp()   { return (op == TOK.prePlusPlus || op == TOK.preMinusMinus) ? cast(typeof(return))this : null; }
1589 0
        inout(AssignExp)    isAssignExp()    { return op == TOK.assign ? cast(typeof(return))this : null; }
1590 1
        inout(ConstructExp) isConstructExp() { return op == TOK.construct ? cast(typeof(return))this : null; }
1591 0
        inout(BlitExp)      isBlitExp()      { return op == TOK.blit ? cast(typeof(return))this : null; }
1592 1
        inout(AddAssignExp) isAddAssignExp() { return op == TOK.addAssign ? cast(typeof(return))this : null; }
1593 0
        inout(MinAssignExp) isMinAssignExp() { return op == TOK.minAssign ? cast(typeof(return))this : null; }
1594 0
        inout(MulAssignExp) isMulAssignExp() { return op == TOK.mulAssign ? cast(typeof(return))this : null; }
1595

1596 0
        inout(DivAssignExp) isDivAssignExp() { return op == TOK.divAssign ? cast(typeof(return))this : null; }
1597 0
        inout(ModAssignExp) isModAssignExp() { return op == TOK.modAssign ? cast(typeof(return))this : null; }
1598 0
        inout(AndAssignExp) isAndAssignExp() { return op == TOK.andAssign ? cast(typeof(return))this : null; }
1599 0
        inout(OrAssignExp)  isOrAssignExp()  { return op == TOK.orAssign ? cast(typeof(return))this : null; }
1600 0
        inout(XorAssignExp) isXorAssignExp() { return op == TOK.xorAssign ? cast(typeof(return))this : null; }
1601 0
        inout(PowAssignExp) isPowAssignExp() { return op == TOK.powAssign ? cast(typeof(return))this : null; }
1602

1603 0
        inout(ShlAssignExp)  isShlAssignExp()  { return op == TOK.leftShiftAssign ? cast(typeof(return))this : null; }
1604 0
        inout(ShrAssignExp)  isShrAssignExp()  { return op == TOK.rightShiftAssign ? cast(typeof(return))this : null; }
1605 0
        inout(UshrAssignExp) isUshrAssignExp() { return op == TOK.unsignedRightShiftAssign ? cast(typeof(return))this : null; }
1606

1607 0
        inout(CatAssignExp) isCatAssignExp() { return op == TOK.concatenateAssign
1608 0
                                                ? cast(typeof(return))this
1609 0
                                                : null; }
1610

1611 0
        inout(CatElemAssignExp) isCatElemAssignExp() { return op == TOK.concatenateElemAssign
1612 0
                                                ? cast(typeof(return))this
1613 0
                                                : null; }
1614

1615 0
        inout(CatDcharAssignExp) isCatDcharAssignExp() { return op == TOK.concatenateDcharAssign
1616 0
                                                ? cast(typeof(return))this
1617 0
                                                : null; }
1618

1619 1
        inout(AddExp)      isAddExp() { return op == TOK.add ? cast(typeof(return))this : null; }
1620 0
        inout(MinExp)      isMinExp() { return op == TOK.min ? cast(typeof(return))this : null; }
1621 0
        inout(CatExp)      isCatExp() { return op == TOK.concatenate ? cast(typeof(return))this : null; }
1622 0
        inout(MulExp)      isMulExp() { return op == TOK.mul ? cast(typeof(return))this : null; }
1623 0
        inout(DivExp)      isDivExp() { return op == TOK.div ? cast(typeof(return))this : null; }
1624 0
        inout(ModExp)      isModExp() { return op == TOK.mod ? cast(typeof(return))this : null; }
1625 0
        inout(PowExp)      isPowExp() { return op == TOK.pow ? cast(typeof(return))this : null; }
1626 0
        inout(ShlExp)      isShlExp() { return op == TOK.leftShift ? cast(typeof(return))this : null; }
1627 0
        inout(ShrExp)      isShrExp() { return op == TOK.rightShift ? cast(typeof(return))this : null; }
1628 0
        inout(UshrExp)     isUshrExp() { return op == TOK.unsignedRightShift ? cast(typeof(return))this : null; }
1629 0
        inout(AndExp)      isAndExp() { return op == TOK.and ? cast(typeof(return))this : null; }
1630 0
        inout(OrExp)       isOrExp() { return op == TOK.or ? cast(typeof(return))this : null; }
1631 0
        inout(XorExp)      isXorExp() { return op == TOK.xor ? cast(typeof(return))this : null; }
1632 0
        inout(LogicalExp)  isLogicalExp() { return (op == TOK.andAnd || op == TOK.orOr) ? cast(typeof(return))this : null; }
1633
        //inout(CmpExp)    isCmpExp() { return op == TOK. ? cast(typeof(return))this : null; }
1634 0
        inout(InExp)       isInExp() { return op == TOK.in_ ? cast(typeof(return))this : null; }
1635 0
        inout(RemoveExp)   isRemoveExp() { return op == TOK.remove ? cast(typeof(return))this : null; }
1636 0
        inout(EqualExp)    isEqualExp() { return (op == TOK.equal || op == TOK.notEqual) ? cast(typeof(return))this : null; }
1637 0
        inout(IdentityExp) isIdentityExp() { return (op == TOK.identity || op == TOK.notIdentity) ? cast(typeof(return))this : null; }
1638 1
        inout(CondExp)     isCondExp() { return op == TOK.question ? cast(typeof(return))this : null; }
1639

1640 0
        inout(DefaultInitExp)    isDefaultInitExp() { return op == TOK.default_ ? cast(typeof(return))this : null; }
1641 0
        inout(FileInitExp)       isFileInitExp() { return (op == TOK.file || op == TOK.fileFullPath) ? cast(typeof(return))this : null; }
1642 0
        inout(LineInitExp)       isLineInitExp() { return op == TOK.line ? cast(typeof(return))this : null; }
1643 0
        inout(ModuleInitExp)     isModuleInitExp() { return op == TOK.moduleString ? cast(typeof(return))this : null; }
1644 0
        inout(FuncInitExp)       isFuncInitExp() { return op == TOK.functionString ? cast(typeof(return))this : null; }
1645 0
        inout(PrettyFuncInitExp) isPrettyFuncInitExp() { return op == TOK.prettyFunction ? cast(typeof(return))this : null; }
1646 1
        inout(ClassReferenceExp) isClassReferenceExp() { return op == TOK.classReference ? cast(typeof(return))this : null; }
1647
    }
1648

1649
    override void accept(Visitor v)
1650
    {
1651 1
        v.visit(this);
1652
    }
1653
}
1654

1655
/***********************************************************
1656
 */
1657
extern (C++) final class IntegerExp : Expression
1658
{
1659
    private dinteger_t value;
1660

1661 1
    extern (D) this(const ref Loc loc, dinteger_t value, Type type)
1662
    {
1663 1
        super(loc, TOK.int64, __traits(classInstanceSize, IntegerExp));
1664
        //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : "");
1665 1
        assert(type);
1666 1
        if (!type.isscalar())
1667
        {
1668
            //printf("%s, loc = %d\n", toChars(), loc.linnum);
1669 1
            if (type.ty != Terror)
1670 1
                error("integral constant must be scalar type, not `%s`", type.toChars());
1671 1
            type = Type.terror;
1672
        }
1673 1
        this.type = type;
1674 1
        this.value = normalize(type.toBasetype().ty, value);
1675
    }
1676

1677 1
    extern (D) this(dinteger_t value)
1678
    {
1679 1
        super(Loc.initial, TOK.int64, __traits(classInstanceSize, IntegerExp));
1680 1
        this.type = Type.tint32;
1681 1
        this.value = cast(d_int32)value;
1682
    }
1683

1684
    static IntegerExp create(Loc loc, dinteger_t value, Type type)
1685
    {
1686 0
        return new IntegerExp(loc, value, type);
1687
    }
1688

1689
    // Same as create, but doesn't allocate memory.
1690
    static void emplace(UnionExp* pue, Loc loc, dinteger_t value, Type type)
1691
    {
1692 0
        emplaceExp!(IntegerExp)(pue, loc, value, type);
1693
    }
1694

1695
    override bool equals(const RootObject o) const
1696
    {
1697 1
        if (this == o)
1698 1
            return true;
1699 1
        if (auto ne = (cast(Expression)o).isIntegerExp())
1700
        {
1701 1
            if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && value == ne.value)
1702
            {
1703 1
                return true;
1704
            }
1705
        }
1706 1
        return false;
1707
    }
1708

1709
    override dinteger_t toInteger()
1710
    {
1711
        // normalize() is necessary until we fix all the paints of 'type'
1712 1
        return value = normalize(type.toBasetype().ty, value);
1713
    }
1714

1715
    override real_t toReal()
1716
    {
1717
        // normalize() is necessary until we fix all the paints of 'type'
1718 1
        const ty = type.toBasetype().ty;
1719 1
        const val = normalize(ty, value);
1720 1
        value = val;
1721 1
        return (ty == Tuns64)
1722 1
            ? real_t(cast(d_uns64)val)
1723 1
            : real_t(cast(d_int64)val);
1724
    }
1725

1726
    override real_t toImaginary()
1727
    {
1728 1
        return CTFloat.zero;
1729
    }
1730

1731
    override complex_t toComplex()
1732
    {
1733 1
        return complex_t(toReal());
1734
    }
1735

1736
    override bool isBool(bool result)
1737
    {
1738 1
        bool r = toInteger() != 0;
1739 1
        return result ? r : !r;
1740
    }
1741

1742
    override Expression toLvalue(Scope* sc, Expression e)
1743
    {
1744 1
        if (!e)
1745 0
            e = this;
1746 1
        else if (!loc.isValid())
1747 0
            loc = e.loc;
1748 1
        e.error("cannot modify constant `%s`", e.toChars());
1749 1
        return ErrorExp.get();
1750
    }
1751

1752
    override void accept(Visitor v)
1753
    {
1754 1
        v.visit(this);
1755
    }
1756

1757
    dinteger_t getInteger()
1758
    {
1759 1
        return value;
1760
    }
1761

1762
    void setInteger(dinteger_t value)
1763
    {
1764 1
        this.value = normalize(type.toBasetype().ty, value);
1765
    }
1766

1767
    extern (D) static dinteger_t normalize(TY ty, dinteger_t value)
1768
    {
1769
        /* 'Normalize' the value of the integer to be in range of the type
1770
         */
1771 1
        dinteger_t result;
1772 1
        switch (ty)
1773
        {
1774 1
        case Tbool:
1775 1
            result = (value != 0);
1776 1
            break;
1777

1778 1
        case Tint8:
1779 1
            result = cast(d_int8)value;
1780 1
            break;
1781

1782 1
        case Tchar:
1783 1
        case Tuns8:
1784 1
            result = cast(d_uns8)value;
1785 1
            break;
1786

1787 1
        case Tint16:
1788 1
            result = cast(d_int16)value;
1789 1
            break;
1790

1791 1
        case Twchar:
1792 1
        case Tuns16:
1793 1
            result = cast(d_uns16)value;
1794 1
            break;
1795

1796 1
        case Tint32:
1797 1
            result = cast(d_int32)value;
1798 1
            break;
1799

1800 1
        case Tdchar:
1801 1
        case Tuns32:
1802 1
            result = cast(d_uns32)value;
1803 1
            break;
1804

1805 1
        case Tint64:
1806 1
            result = cast(d_int64)value;
1807 1
            break;
1808

1809 1
        case Tuns64:
1810 1
            result = cast(d_uns64)value;
1811 1
            break;
1812

1813 1
        case Tpointer:
1814 1
            if (target.ptrsize == 8)
1815 1
                goto case Tuns64;
1816 1
            if (target.ptrsize == 4)
1817 1
                goto case Tuns32;
1818 0
            if (target.ptrsize == 2)
1819 0
                goto case Tuns16;
1820 0
            assert(0);
1821

1822 1
        default:
1823 1
            break;
1824
        }
1825 1
        return result;
1826
    }
1827

1828
    override Expression syntaxCopy()
1829
    {
1830 1
        return this;
1831
    }
1832

1833
    /**
1834
     * Use this instead of creating new instances for commonly used literals
1835
     * such as 0 or 1.
1836
     *
1837
     * Parameters:
1838
     *      v = The value of the expression
1839
     * Returns:
1840
     *      A static instance of the expression, typed as `Tint32`.
1841
     */
1842
    static IntegerExp literal(int v)()
1843
    {
1844 1
        __gshared IntegerExp theConstant;
1845 1
        if (!theConstant)
1846 1
            theConstant = new IntegerExp(v);
1847 1
        return theConstant;
1848
    }
1849

1850
    /**
1851
     * Use this instead of creating new instances for commonly used bools.
1852
     *
1853
     * Parameters:
1854
     *      b = The value of the expression
1855
     * Returns:
1856
     *      A static instance of the expression, typed as `Type.tbool`.
1857
     */
1858
    static IntegerExp createBool(bool b)
1859
    {
1860 1
        __gshared IntegerExp trueExp, falseExp;
1861 1
        if (!trueExp)
1862
        {
1863 1
            trueExp = new IntegerExp(Loc.initial, 1, Type.tbool);
1864 1
            falseExp = new IntegerExp(Loc.initial, 0, Type.tbool);
1865
        }
1866 1
        return b ? trueExp : falseExp;
1867
    }
1868
}
1869

1870
/***********************************************************
1871
 * Use this expression for error recovery.
1872
 * It should behave as a 'sink' to prevent further cascaded error messages.
1873
 */
1874
extern (C++) final class ErrorExp : Expression
1875
{
1876 1
    private extern (D) this()
1877
    {
1878 1
        super(Loc.initial, TOK.error, __traits(classInstanceSize, ErrorExp));
1879 1
        type = Type.terror;
1880
    }
1881

1882
    static ErrorExp get ()
1883
    {
1884 1
        if (errorexp is null)
1885 1
            errorexp = new ErrorExp();
1886

1887 1
        if (global.errors == 0 && global.gaggedErrors == 0)
1888
        {
1889
            /* Unfortunately, errors can still leak out of gagged errors,
1890
              * and we need to set the error count to prevent bogus code
1891
              * generation. At least give a message.
1892
              */
1893 1
            .error(Loc.initial, "unknown, please file report on issues.dlang.org");
1894
        }
1895

1896 1
        return errorexp;
1897
    }
1898

1899
    override Expression toLvalue(Scope* sc, Expression e)
1900
    {
1901 1
        return this;
1902
    }
1903

1904
    override void accept(Visitor v)
1905
    {
1906 1
        v.visit(this);
1907
    }
1908

1909
    extern (C++) __gshared ErrorExp errorexp; // handy shared value
1910
}
1911

1912

1913
/***********************************************************
1914
 * An uninitialized value,
1915
 * generated from void initializers.
1916
 */
1917
extern (C++) final class VoidInitExp : Expression
1918
{
1919
    VarDeclaration var; /// the variable from where the void value came from, null if not known
1920
                        /// Useful for error messages
1921

1922 1
    extern (D) this(VarDeclaration var)
1923
    {
1924 1
        super(var.loc, TOK.void_, __traits(classInstanceSize, VoidInitExp));
1925 1
        this.var = var;
1926 1
        this.type = var.type;
1927
    }
1928

1929
    override const(char)* toChars() const
1930
    {
1931 0
        return "void";
1932
    }
1933

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

1940

1941
/***********************************************************
1942
 */
1943
extern (C++) final class RealExp : Expression
1944
{
1945
    real_t value;
1946

1947 1
    extern (D) this(const ref Loc loc, real_t value, Type type)
1948
    {
1949 1
        super(loc, TOK.float64, __traits(classInstanceSize, RealExp));
1950
        //printf("RealExp::RealExp(%Lg)\n", value);
1951 1
        this.value = value;
1952 1
        this.type = type;
1953
    }
1954

1955
    static RealExp create(Loc loc, real_t value, Type type)
1956
    {
1957 0
        return new RealExp(loc, value, type);
1958
    }
1959

1960
    // Same as create, but doesn't allocate memory.
1961
    static void emplace(UnionExp* pue, Loc loc, real_t value, Type type)
1962
    {
1963 0
        emplaceExp!(RealExp)(pue, loc, value, type);
1964
    }
1965

1966
    override bool equals(const RootObject o) const
1967
    {
1968 1
        if (this == o)
1969 0
            return true;
1970 1
        if (auto ne = (cast(Expression)o).isRealExp())
1971
        {
1972 1
            if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && RealIdentical(value, ne.value))
1973
            {
1974 1
                return true;
1975
            }
1976
        }
1977 1
        return false;
1978
    }
1979

1980
    override dinteger_t toInteger()
1981
    {
1982 1
        return cast(sinteger_t)toReal();
1983
    }
1984

1985
    override uinteger_t toUInteger()
1986
    {
1987 0
        return cast(uinteger_t)toReal();
1988
    }
1989

1990
    override real_t toReal()
1991
    {
1992 1
        return type.isreal() ? value : CTFloat.zero;
1993
    }
1994

1995
    override real_t toImaginary()
1996
    {
1997 1
        return type.isreal() ? CTFloat.zero : value;
1998
    }
1999

2000
    override complex_t toComplex()
2001
    {
2002 1
        return complex_t(toReal(), toImaginary());
2003
    }
2004

2005
    override bool isBool(bool result)
2006
    {
2007 1
        return result ? cast(bool)value : !cast(bool)value;
2008
    }
2009

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

2016
/***********************************************************
2017
 */
2018
extern (C++) final class ComplexExp : Expression
2019
{
2020
    complex_t value;
2021

2022 1
    extern (D) this(const ref Loc loc, complex_t value, Type type)
2023
    {
2024 1
        super(loc, TOK.complex80, __traits(classInstanceSize, ComplexExp));
2025 1
        this.value = value;
2026 1
        this.type = type;
2027
        //printf("ComplexExp::ComplexExp(%s)\n", toChars());
2028
    }
2029

2030
    static ComplexExp create(Loc loc, complex_t value, Type type)
2031
    {
2032 0
        return new ComplexExp(loc, value, type);
2033
    }
2034

2035
    // Same as create, but doesn't allocate memory.
2036
    static void emplace(UnionExp* pue, Loc loc, complex_t value, Type type)
2037
    {
2038 0
        emplaceExp!(ComplexExp)(pue, loc, value, type);
2039
    }
2040

2041
    override bool equals(const RootObject o) const
2042
    {
2043 0
        if (this == o)
2044 0
            return true;
2045 0
        if (auto ne = (cast(Expression)o).isComplexExp())
2046
        {
2047 0
            if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && RealIdentical(creall(value), creall(ne.value)) && RealIdentical(cimagl(value), cimagl(ne.value)))
2048
            {
2049 0
                return true;
2050
            }
2051
        }
2052 0
        return false;
2053
    }
2054

2055
    override dinteger_t toInteger()
2056
    {
2057 0
        return cast(sinteger_t)toReal();
2058
    }
2059

2060
    override uinteger_t toUInteger()
2061
    {
2062 0
        return cast(uinteger_t)toReal();
2063
    }
2064

2065
    override real_t toReal()
2066
    {
2067 1
        return creall(value);
2068
    }
2069

2070
    override real_t toImaginary()
2071
    {
2072 1
        return cimagl(value);
2073
    }
2074

2075
    override complex_t toComplex()
2076
    {
2077 1
        return value;
2078
    }
2079

2080
    override bool isBool(bool result)
2081
    {
2082 1
        if (result)
2083 0
            return cast(bool)value;
2084
        else
2085 1
            return !value;
2086
    }
2087

2088
    override void accept(Visitor v)
2089
    {
2090 1
        v.visit(this);
2091
    }
2092
}
2093

2094
/***********************************************************
2095
 */
2096
extern (C++) class IdentifierExp : Expression
2097
{
2098
    Identifier ident;
2099

2100 1
    extern (D) this(const ref Loc loc, Identifier ident)
2101
    {
2102 1
        super(loc, TOK.identifier, __traits(classInstanceSize, IdentifierExp));
2103 1
        this.ident = ident;
2104
    }
2105

2106
    static IdentifierExp create(Loc loc, Identifier ident)
2107
    {
2108 1
        return new IdentifierExp(loc, ident);
2109
    }
2110

2111
    override final bool isLvalue()
2112
    {
2113 1
        return true;
2114
    }
2115

2116
    override final Expression toLvalue(Scope* sc, Expression e)
2117
    {
2118 0
        return this;
2119
    }
2120

2121
    override void accept(Visitor v)
2122
    {
2123 1
        v.visit(this);
2124
    }
2125
}
2126

2127
/***********************************************************
2128
 */
2129
extern (C++) final class DollarExp : IdentifierExp
2130
{
2131 1
    extern (D) this(const ref Loc loc)
2132
    {
2133 1
        super(loc, Id.dollar);
2134
    }
2135

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

2142
/***********************************************************
2143
 * Won't be generated by parser.
2144
 */
2145
extern (C++) final class DsymbolExp : Expression
2146
{
2147
    Dsymbol s;
2148
    bool hasOverloads;
2149

2150 1
    extern (D) this(const ref Loc loc, Dsymbol s, bool hasOverloads = true)
2151
    {
2152 1
        super(loc, TOK.dSymbol, __traits(classInstanceSize, DsymbolExp));
2153 1
        this.s = s;
2154 1
        this.hasOverloads = hasOverloads;
2155
    }
2156

2157
    override bool isLvalue()
2158
    {
2159 0
        return true;
2160
    }
2161

2162
    override Expression toLvalue(Scope* sc, Expression e)
2163
    {
2164 0
        return this;
2165
    }
2166

2167
    override void accept(Visitor v)
2168
    {
2169 1
        v.visit(this);
2170
    }
2171
}
2172

2173
/***********************************************************
2174
 * http://dlang.org/spec/expression.html#this
2175
 */
2176
extern (C++) class ThisExp : Expression
2177
{
2178
    VarDeclaration var;
2179

2180 1
    extern (D) this(const ref Loc loc)
2181
    {
2182 1
        super(loc, TOK.this_, __traits(classInstanceSize, ThisExp));
2183
        //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
2184
    }
2185

2186 1
    this(const ref Loc loc, const TOK tok)
2187
    {
2188 1
        super(loc, tok, __traits(classInstanceSize, ThisExp));
2189
        //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
2190
    }
2191

2192
    override Expression syntaxCopy()
2193
    {
2194 1
        auto r = cast(ThisExp) super.syntaxCopy();
2195
        // require new semantic (possibly new `var` etc.)
2196 1
        r.type = null;
2197 1
        r.var = null;
2198 1
        return r;
2199
    }
2200

2201
    override final bool isBool(bool result)
2202
    {
2203 1
        return result;
2204
    }
2205

2206
    override final bool isLvalue()
2207
    {
2208
        // Class `this` should be an rvalue; struct `this` should be an lvalue.
2209 1
        return type.toBasetype().ty != Tclass;
2210
    }
2211

2212
    override final Expression toLvalue(Scope* sc, Expression e)
2213
    {
2214 1
        if (type.toBasetype().ty == Tclass)
2215
        {
2216
            // Class `this` is an rvalue; struct `this` is an lvalue.
2217 1
            return Expression.toLvalue(sc, e);
2218
        }
2219 1
        return this;
2220
    }
2221

2222
    override void accept(Visitor v)
2223
    {
2224 1
        v.visit(this);
2225
    }
2226
}
2227

2228
/***********************************************************
2229
 * http://dlang.org/spec/expression.html#super
2230
 */
2231
extern (C++) final class SuperExp : ThisExp
2232
{
2233 1
    extern (D) this(const ref Loc loc)
2234
    {
2235 1
        super(loc, TOK.super_);
2236
    }
2237

2238
    override void accept(Visitor v)
2239
    {
2240 1
        v.visit(this);
2241
    }
2242
}
2243

2244
/***********************************************************
2245
 * http://dlang.org/spec/expression.html#null
2246
 */
2247
extern (C++) final class NullExp : Expression
2248
{
2249 1
    extern (D) this(const ref Loc loc, Type type = null)
2250
    {
2251 1
        super(loc, TOK.null_, __traits(classInstanceSize, NullExp));
2252 1
        this.type = type;
2253
    }
2254

2255
    override bool equals(const RootObject o) const
2256
    {
2257 1
        if (auto e = o.isExpression())
2258
        {
2259 1
            if (e.op == TOK.null_ && type.equals(e.type))
2260
            {
2261 1
                return true;
2262
            }
2263
        }
2264 1
        return false;
2265
    }
2266

2267
    override bool isBool(bool result)
2268
    {
2269 1
        return result ? false : true;
2270
    }
2271

2272
    override StringExp toStringExp()
2273
    {
2274 1
        if (implicitConvTo(Type.tstring))
2275
        {
2276 1
            auto se = new StringExp(loc, (cast(char*)mem.xcalloc(1, 1))[0 .. 0]);
2277 1
            se.type = Type.tstring;
2278 1
            return se;
2279
        }
2280 1
        return null;
2281
    }
2282

2283
    override void accept(Visitor v)
2284
    {
2285 1
        v.visit(this);
2286
    }
2287
}
2288

2289
/***********************************************************
2290
 * http://dlang.org/spec/expression.html#string_literals
2291
 */
2292
extern (C++) final class StringExp : Expression
2293
{
2294
    private union
2295
    {
2296
        char* string;   // if sz == 1
2297
        wchar* wstring; // if sz == 2
2298
        dchar* dstring; // if sz == 4
2299
    }                   // (const if ownedByCtfe == OwnedBy.code)
2300
    size_t len;         // number of code units
2301
    ubyte sz = 1;       // 1: char, 2: wchar, 4: dchar
2302
    ubyte committed;    // !=0 if type is committed
2303
    enum char NoPostfix = 0;
2304
    char postfix = NoPostfix;   // 'c', 'w', 'd'
2305
    OwnedBy ownedByCtfe = OwnedBy.code;
2306

2307 1
    extern (D) this(const ref Loc loc, const(void)[] string)
2308
    {
2309 1
        super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
2310 1
        this.string = cast(char*)string.ptr; // note that this.string should be const
2311 1
        this.len = string.length;
2312 1
        this.sz = 1;                    // work around LDC bug #1286
2313
    }
2314

2315 1
    extern (D) this(const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix)
2316
    {
2317 1
        super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
2318 1
        this.string = cast(char*)string.ptr; // note that this.string should be const
2319 1
        this.len = len;
2320 1
        this.sz = sz;
2321 1
        this.postfix = postfix;
2322
    }
2323

2324
    static StringExp create(Loc loc, char* s)
2325
    {
2326 1
        return new StringExp(loc, s.toDString());
2327
    }
2328

2329
    static StringExp create(Loc loc, void* string, size_t len)
2330
    {
2331 0
        return new StringExp(loc, string[0 .. len]);
2332
    }
2333

2334
    // Same as create, but doesn't allocate memory.
2335
    static void emplace(UnionExp* pue, Loc loc, char* s)
2336
    {
2337 0
        emplaceExp!(StringExp)(pue, loc, s.toDString());
2338
    }
2339

2340
    extern (D) static void emplace(UnionExp* pue, Loc loc, const(void)[] string)
2341
    {
2342 0
        emplaceExp!(StringExp)(pue, loc, string);
2343
    }
2344

2345
    extern (D) static void emplace(UnionExp* pue, Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix)
2346
    {
2347 0
        emplaceExp!(StringExp)(pue, loc, string, len, sz, postfix);
2348
    }
2349

2350
    override bool equals(const RootObject o) const
2351
    {
2352
        //printf("StringExp::equals('%s') %s\n", o.toChars(), toChars());
2353 1
        if (auto e = o.isExpression())
2354
        {
2355 1
            if (auto se = e.isStringExp())
2356
            {
2357 1
                return compare(se) == 0;
2358
            }
2359
        }
2360 0
        return false;
2361
    }
2362

2363
    /**********************************
2364
     * Return the number of code units the string would be if it were re-encoded
2365
     * as tynto.
2366
     * Params:
2367
     *      tynto = code unit type of the target encoding
2368
     * Returns:
2369
     *      number of code units
2370
     */
2371
    size_t numberOfCodeUnits(int tynto = 0) const
2372
    {
2373 1
        int encSize;
2374 1
        switch (tynto)
2375
        {
2376 1
            case 0:      return len;
2377 1
            case Tchar:  encSize = 1; break;
2378 1
            case Twchar: encSize = 2; break;
2379 1
            case Tdchar: encSize = 4; break;
2380 0
            default:
2381 0
                assert(0);
2382
        }
2383 1
        if (sz == encSize)
2384 1
            return len;
2385

2386 1
        size_t result = 0;
2387 1
        dchar c;
2388

2389 1
        switch (sz)
2390
        {
2391 1
        case 1:
2392 1
            for (size_t u = 0; u < len;)
2393
            {
2394 1
                if (const s = utf_decodeChar(string[0 .. len], u, c))
2395
                {
2396 0
                    error("%.*s", cast(int)s.length, s.ptr);
2397 0
                    return 0;
2398
                }
2399 1
                result += utf_codeLength(encSize, c);
2400
            }
2401 1
            break;
2402

2403 0
        case 2:
2404 0
            for (size_t u = 0; u < len;)
2405
            {
2406 0
                if (const s = utf_decodeWchar(wstring[0 .. len], u, c))
2407
                {
2408 0
                    error("%.*s", cast(int)s.length, s.ptr);
2409 0
                    return 0;
2410
                }
2411 0
                result += utf_codeLength(encSize, c);
2412
            }
2413 0
            break;
2414

2415 0
        case 4:
2416 0
            foreach (u; 0 .. len)
2417
            {
2418 0
                result += utf_codeLength(encSize, dstring[u]);
2419
            }
2420 0
            break;
2421

2422 0
        default:
2423 0
            assert(0);
2424
        }
2425 1
        return result;
2426
    }
2427

2428
    /**********************************************
2429
     * Write the contents of the string to dest.
2430
     * Use numberOfCodeUnits() to determine size of result.
2431
     * Params:
2432
     *  dest = destination
2433
     *  tyto = encoding type of the result
2434
     *  zero = add terminating 0
2435
     */
2436
    void writeTo(void* dest, bool zero, int tyto = 0) const
2437
    {
2438 1
        int encSize;
2439 1
        switch (tyto)
2440
        {
2441 1
            case 0:      encSize = sz; break;
2442 0
            case Tchar:  encSize = 1; break;
2443 0
            case Twchar: encSize = 2; break;
2444 0
            case Tdchar: encSize = 4; break;
2445 0
            default:
2446 0
                assert(0);
2447
        }
2448 1
        if (sz == encSize)
2449
        {
2450 1
            memcpy(dest, string, len * sz);
2451 1
            if (zero)
2452 1
                memset(dest + len * sz, 0, sz);
2453
        }
2454
        else
2455 0
            assert(0);
2456
    }
2457

2458
    /*********************************************
2459
     * Get the code unit at index i
2460
     * Params:
2461
     *  i = index
2462
     * Returns:
2463
     *  code unit at index i
2464
     */
2465
    dchar getCodeUnit(size_t i) const pure
2466
    {
2467 1
        assert(i < len);
2468 1
        final switch (sz)
2469
        {
2470 1
        case 1:
2471 1
            return string[i];
2472 1
        case 2:
2473 1
            return wstring[i];
2474 1
        case 4:
2475 1
            return dstring[i];
2476
        }
2477
    }
2478

2479
    /*********************************************
2480
     * Set the code unit at index i to c
2481
     * Params:
2482
     *  i = index
2483
     *  c = code unit to set it to
2484
     */
2485
    void setCodeUnit(size_t i, dchar c)
2486
    {
2487 1
        assert(i < len);
2488 1
        final switch (sz)
2489
        {
2490 1
        case 1:
2491 1
            string[i] = cast(char)c;
2492 1
            break;
2493 0
        case 2:
2494 0
            wstring[i] = cast(wchar)c;
2495 0
            break;
2496 0
        case 4:
2497 0
            dstring[i] = c;
2498 0
            break;
2499
        }
2500
    }
2501

2502
    override StringExp toStringExp()
2503
    {
2504 1
        return this;
2505
    }
2506

2507
    /****************************************
2508
     * Convert string to char[].
2509
     */
2510
    StringExp toUTF8(Scope* sc)
2511
    {
2512 1
        if (sz != 1)
2513
        {
2514
            // Convert to UTF-8 string
2515 1
            committed = 0;
2516 1
            Expression e = castTo(sc, Type.tchar.arrayOf());
2517 1
            e = e.optimize(WANTvalue);
2518 1
            auto se = e.isStringExp();
2519 1
            assert(se.sz == 1);
2520 1
            return se;
2521
        }
2522 1
        return this;
2523
    }
2524

2525
    /**
2526
     * Compare two `StringExp` by length, then value
2527
     *
2528
     * The comparison is not the usual C-style comparison as seen with
2529
     * `strcmp` or `memcmp`, but instead first compare based on the length.
2530
     * This allows both faster lookup and sorting when comparing sparse data.
2531
     *
2532
     * This ordering scheme is relied on by the string-switching feature.
2533
     * Code in Druntime's `core.internal.switch_` relies on this ordering
2534
     * when doing a binary search among case statements.
2535
     *
2536
     * Both `StringExp` should be of the same encoding.
2537
     *
2538
     * Params:
2539
     *   se2 = String expression to compare `this` to
2540
     *
2541
     * Returns:
2542
     *   `0` when `this` is equal to se2, a value greater than `0` if
2543
     *   `this` should be considered greater than `se2`,
2544
     *   and a value less than `0` if `this` is lesser than `se2`.
2545
     */
2546
    int compare(const StringExp se2) const nothrow pure @nogc
2547
    {
2548
        //printf("StringExp::compare()\n");
2549 1
        const len1 = len;
2550 1
        const len2 = se2.len;
2551

2552 1
        assert(this.sz == se2.sz, "Comparing string expressions of different sizes");
2553
        //printf("sz = %d, len1 = %d, len2 = %d\n", sz, (int)len1, (int)len2);
2554 1
        if (len1 == len2)
2555
        {
2556 1
            switch (sz)
2557
            {
2558 1
            case 1:
2559 1
                return memcmp(string, se2.string, len1);
2560

2561 0
            case 2:
2562
                {
2563 0
                    wchar* s1 = cast(wchar*)string;
2564 0
                    wchar* s2 = cast(wchar*)se2.string;
2565 0
                    foreach (u; 0 .. len)
2566
                    {
2567 0
                        if (s1[u] != s2[u])
2568 0
                            return s1[u] - s2[u];
2569
                    }
2570
                }
2571 0
                break;
2572 1
            case 4:
2573
                {
2574 1
                    dchar* s1 = cast(dchar*)string;
2575 1
                    dchar* s2 = cast(dchar*)se2.string;
2576 1
                    foreach (u; 0 .. len)
2577
                    {
2578 1
                        if (s1[u] != s2[u])
2579 1
                            return s1[u] - s2[u];
2580
                    }
2581
                }
2582 0
                break;
2583 0
            default:
2584 0
                assert(0);
2585
            }
2586
        }
2587 1
        return cast(int)(len1 - len2);
2588
    }
2589

2590
    override bool isBool(bool result)
2591
    {
2592 1
        return result;
2593
    }
2594

2595
    override bool isLvalue()
2596
    {
2597
        /* string literal is rvalue in default, but
2598
         * conversion to reference of static array is only allowed.
2599
         */
2600 1
        return (type && type.toBasetype().ty == Tsarray);
2601
    }
2602

2603
    override Expression toLvalue(Scope* sc, Expression e)
2604
    {
2605
        //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type.toChars() : NULL);
2606 1
        return (type && type.toBasetype().ty == Tsarray) ? this : Expression.toLvalue(sc, e);
2607
    }
2608

2609
    override Expression modifiableLvalue(Scope* sc, Expression e)
2610
    {
2611 1
        error("cannot modify string literal `%s`", toChars());
2612 1
        return ErrorExp.get();
2613
    }
2614

2615
    uint charAt(uinteger_t i) const
2616
    {
2617 1
        uint value;
2618 1
        switch (sz)
2619
        {
2620 1
        case 1:
2621 1
            value = (cast(char*)string)[cast(size_t)i];
2622 1
            break;
2623

2624 1
        case 2:
2625 1
            value = (cast(ushort*)string)[cast(size_t)i];
2626 1
            break;
2627

2628 1
        case 4:
2629 1
            value = (cast(uint*)string)[cast(size_t)i];
2630 1
            break;
2631

2632 0
        default:
2633 0
            assert(0);
2634
        }
2635 1
        return value;
2636
    }
2637

2638
    /********************************
2639
     * Convert string contents to a 0 terminated string,
2640
     * allocated by mem.xmalloc().
2641
     */
2642
    extern (D) const(char)[] toStringz() const
2643
    {
2644 1
        auto nbytes = len * sz;
2645 1
        char* s = cast(char*)mem.xmalloc(nbytes + sz);
2646 1
        writeTo(s, true);
2647 1
        return s[0 .. nbytes];
2648
    }
2649

2650
    extern (D) const(char)[] peekString() const
2651
    {
2652 1
        assert(sz == 1);
2653 1
        return this.string[0 .. len];
2654
    }
2655

2656
    extern (D) const(wchar)[] peekWstring() const
2657
    {
2658 1
        assert(sz == 2);
2659 1
        return this.wstring[0 .. len];
2660
    }
2661

2662
    extern (D) const(dchar)[] peekDstring() const
2663
    {
2664 1
        assert(sz == 4);
2665 1
        return this.dstring[0 .. len];
2666
    }
2667

2668
    /*******************
2669
     * Get a slice of the data.
2670
     */
2671
    extern (D) const(ubyte)[] peekData() const
2672
    {
2673 1
        return cast(const(ubyte)[])this.string[0 .. len * sz];
2674
    }
2675

2676
    /*******************
2677
     * Borrow a slice of the data, so the caller can modify
2678
     * it in-place (!)
2679
     */
2680
    extern (D) ubyte[] borrowData()
2681
    {
2682 1
        return cast(ubyte[])this.string[0 .. len * sz];
2683
    }
2684

2685
    /***********************
2686
     * Set new string data.
2687
     * `this` becomes the new owner of the data.
2688
     */
2689
    extern (D) void setData(void* s, size_t len, ubyte sz)
2690
    {
2691 1
        this.string = cast(char*)s;
2692 1
        this.len = len;
2693 1
        this.sz = sz;
2694
    }
2695

2696
    override void accept(Visitor v)
2697
    {
2698 1
        v.visit(this);
2699
    }
2700
}
2701

2702
/***********************************************************
2703
 */
2704
extern (C++) final class TupleExp : Expression
2705
{
2706
    /* Tuple-field access may need to take out its side effect part.
2707
     * For example:
2708
     *      foo().tupleof
2709
     * is rewritten as:
2710
     *      (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...))
2711
     * The declaration of temporary variable __tup will be stored in TupleExp.e0.
2712
     */
2713
    Expression e0;
2714

2715
    Expressions* exps;
2716

2717 1
    extern (D) this(const ref Loc loc, Expression e0, Expressions* exps)
2718
    {
2719 1
        super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
2720
        //printf("TupleExp(this = %p)\n", this);
2721 1
        this.e0 = e0;
2722 1
        this.exps = exps;
2723
    }
2724

2725 1
    extern (D) this(const ref Loc loc, Expressions* exps)
2726
    {
2727 1
        super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
2728
        //printf("TupleExp(this = %p)\n", this);
2729 1
        this.exps = exps;
2730
    }
2731

2732 1
    extern (D) this(const ref Loc loc, TupleDeclaration tup)
2733
    {
2734 1
        super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
2735 1
        this.exps = new Expressions();
2736

2737 1
        this.exps.reserve(tup.objects.dim);
2738 1
        foreach (o; *tup.objects)
2739
        {
2740 1
            if (Dsymbol s = getDsymbol(o))
2741
            {
2742
                /* If tuple element represents a symbol, translate to DsymbolExp
2743
                 * to supply implicit 'this' if needed later.
2744
                 */
2745 1
                Expression e = new DsymbolExp(loc, s);
2746 1
                this.exps.push(e);
2747
            }
2748 1
            else if (auto eo = o.isExpression())
2749
            {
2750 1
                auto e = eo.copy();
2751 1
                e.loc = loc;    // https://issues.dlang.org/show_bug.cgi?id=15669
2752 1
                this.exps.push(e);
2753
            }
2754 1
            else if (auto t = o.isType())
2755
            {
2756 1
                Expression e = new TypeExp(loc, t);
2757 1
                this.exps.push(e);
2758
            }
2759
            else
2760
            {
2761 0
                error("`%s` is not an expression", o.toChars());
2762
            }
2763
        }
2764
    }
2765

2766
    static TupleExp create(Loc loc, Expressions* exps)
2767
    {
2768 0
        return new TupleExp(loc, exps);
2769
    }
2770

2771
    override TupleExp toTupleExp()
2772
    {
2773 1
        return this;
2774
    }
2775

2776
    override Expression syntaxCopy()
2777
    {
2778 1
        return new TupleExp(loc, e0 ? e0.syntaxCopy() : null, arraySyntaxCopy(exps));
2779
    }
2780

2781
    override bool equals(const RootObject o) const
2782
    {
2783 0
        if (this == o)
2784 0
            return true;
2785 0
        if (auto e = o.isExpression())
2786 0
            if (auto te = e.isTupleExp())
2787
            {
2788 0
                if (exps.dim != te.exps.dim)
2789 0
                    return false;
2790 0
                if (e0 && !e0.equals(te.e0) || !e0 && te.e0)
2791 0
                    return false;
2792 0
                foreach (i, e1; *exps)
2793
                {
2794 0
                    auto e2 = (*te.exps)[i];
2795 0
                    if (!e1.equals(e2))
2796 0
                        return false;
2797
                }
2798 0
                return true;
2799
            }
2800 0
        return false;
2801
    }
2802

2803
    override void accept(Visitor v)
2804
    {
2805 1
        v.visit(this);
2806
    }
2807
}
2808

2809
/***********************************************************
2810
 * [ e1, e2, e3, ... ]
2811
 *
2812
 * http://dlang.org/spec/expression.html#array_literals
2813
 */
2814
extern (C++) final class ArrayLiteralExp : Expression
2815
{
2816
    /** If !is null, elements[] can be sparse and basis is used for the
2817
     * "default" element value. In other words, non-null elements[i] overrides
2818
     * this 'basis' value.
2819
     */
2820
    Expression basis;
2821

2822
    Expressions* elements;
2823
    OwnedBy ownedByCtfe = OwnedBy.code;
2824

2825

2826 1
    extern (D) this(const ref Loc loc, Type type, Expressions* elements)
2827
    {
2828 1
        super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
2829 1
        this.type = type;
2830 1
        this.elements = elements;
2831
    }
2832

2833 1
    extern (D) this(const ref Loc loc, Type type, Expression e)
2834
    {
2835 1
        super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
2836 1
        this.type = type;
2837 1
        elements = new Expressions();
2838 1
        elements.push(e);
2839
    }
2840

2841 1
    extern (D) this(const ref Loc loc, Type type, Expression basis, Expressions* elements)
2842
    {
2843 1
        super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
2844 1
        this.type = type;
2845 1
        this.basis = basis;
2846 1
        this.elements = elements;
2847
    }
2848

2849
    static ArrayLiteralExp create(Loc loc, Expressions* elements)
2850
    {
2851 0
        return new ArrayLiteralExp(loc, null, elements);
2852
    }
2853

2854
    // Same as create, but doesn't allocate memory.
2855
    static void emplace(UnionExp* pue, Loc loc, Expressions* elements)
2856
    {
2857 0
        emplaceExp!(ArrayLiteralExp)(pue, loc, null, elements);
2858
    }
2859

2860
    override Expression syntaxCopy()
2861
    {
2862 1
        return new ArrayLiteralExp(loc,
2863
            null,
2864 1
            basis ? basis.syntaxCopy() : null,
2865
            arraySyntaxCopy(elements));
2866
    }
2867

2868
    override bool equals(const RootObject o) const
2869
    {
2870 1
        if (this == o)
2871 0
            return true;
2872 1
        auto e = o.isExpression();
2873 1
        if (!e)
2874 0
            return false;
2875 1
        if (auto ae = e.isArrayLiteralExp())
2876
        {
2877 1
            if (elements.dim != ae.elements.dim)
2878 0
                return false;
2879 1
            if (elements.dim == 0 && !type.equals(ae.type))
2880
            {
2881 0
                return false;
2882
            }
2883

2884 1
            foreach (i, e1; *elements)
2885
            {
2886 1
                auto e2 = (*ae.elements)[i];
2887 1
                auto e1x = e1 ? e1 : basis;
2888 1
                auto e2x = e2 ? e2 : ae.basis;
2889

2890 1
                if (e1x != e2x && (!e1x || !e2x || !e1x.equals(e2x)))
2891 0
                    return false;
2892
            }
2893 1
            return true;
2894
        }
2895 0
        return false;
2896
    }
2897

2898
    Expression getElement(size_t i)
2899
    {
2900 0
        return this[i];
2901
    }
2902

2903
    Expression opIndex(size_t i)
2904
    {
2905 1
        auto el = (*elements)[i];
2906 1
        return el ? el : basis;
2907
    }
2908

2909
    override bool isBool(bool result)
2910
    {
2911 1
        size_t dim = elements ? elements.dim : 0;
2912 1
        return result ? (dim != 0) : (dim == 0);
2913
    }
2914

2915
    override StringExp toStringExp()
2916
    {
2917 1
        TY telem = type.nextOf().toBasetype().ty;
2918 1
        if (telem.isSomeChar || (telem == Tvoid && (!elements || elements.dim == 0)))
2919
        {
2920 1
            ubyte sz = 1;
2921 1
            if (telem == Twchar)
2922 1
                sz = 2;
2923 1
            else if (telem == Tdchar)
2924 1
                sz = 4;
2925

2926 1
            OutBuffer buf;
2927 1
            if (elements)
2928
            {
2929 1
                foreach (i; 0 .. elements.dim)
2930
                {
2931 1
                    auto ch = this[i];
2932 1
                    if (ch.op != TOK.int64)
2933 0
                        return null;
2934 1
                    if (sz == 1)
2935 1
                        buf.writeByte(cast(uint)ch.toInteger());
2936 1
                    else if (sz == 2)
2937 1
                        buf.writeword(cast(uint)ch.toInteger());
2938
                    else
2939 1
                        buf.write4(cast(uint)ch.toInteger());
2940
                }
2941
            }
2942 1
            char prefix;
2943 1
            if (sz == 1)
2944
            {
2945 1
                prefix = 'c';
2946 1
                buf.writeByte(0);
2947
            }
2948 1
            else if (sz == 2)
2949
            {
2950 1
                prefix = 'w';
2951 1
                buf.writeword(0);
2952
            }
2953
            else
2954
            {
2955 1
                prefix = 'd';
2956 1
                buf.write4(0);
2957
            }
2958