2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/expression.c
11 #include "root/dsystem.h"
12 #include "root/rmem.h"
13 #include "root/root.h"
18 #include "expression.h"
23 #include "statement.h"
24 #include "declaration.h"
25 #include "aggregate.h"
39 bool walkPostorder(Expression
*e
, StoppableVisitor
*v
);
40 bool checkParamArgumentEscape(Scope
*sc
, FuncDeclaration
*fdc
, Identifier
*par
, Expression
*arg
, bool gag
);
41 bool checkAccess(AggregateDeclaration
*ad
, Loc loc
, Scope
*sc
, Dsymbol
*smember
);
42 VarDeclaration
*copyToTemp(StorageClass stc
, const char *name
, Expression
*e
);
43 Expression
*extractSideEffect(Scope
*sc
, const char *name
, Expression
**e0
, Expression
*e
, bool alwaysCopy
= false);
44 char *MODtoChars(MOD mod
);
45 bool MODimplicitConv(MOD modfrom
, MOD modto
);
46 MOD
MODmerge(MOD mod1
, MOD mod2
);
47 void MODMatchToBuffer(OutBuffer
*buf
, unsigned char lhsMod
, unsigned char rhsMod
);
48 Expression
*trySemantic(Expression
*e
, Scope
*sc
);
49 Expression
*semantic(Expression
*e
, Scope
*sc
);
50 Expression
*semanticX(DotIdExp
*exp
, Scope
*sc
);
51 Expression
*semanticY(DotIdExp
*exp
, Scope
*sc
, int flag
);
52 Expression
*semanticY(DotTemplateInstanceExp
*exp
, Scope
*sc
, int flag
);
53 Expression
*resolve(Loc loc
, Scope
*sc
, Dsymbol
*s
, bool hasOverloads
);
54 bool checkUnsafeAccess(Scope
*sc
, Expression
*e
, bool readonly
, bool printmsg
);
56 /*************************************************************
57 * Given var, we need to get the
58 * right 'this' pointer if var is in an outer class, but our
59 * existing 'this' pointer is in an inner class.
62 * ad struct or class we need the correct 'this' for
63 * var the specific member of ad we're accessing
66 Expression
*getRightThis(Loc loc
, Scope
*sc
, AggregateDeclaration
*ad
,
67 Expression
*e1
, Declaration
*var
, int flag
= 0)
69 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
71 Type
*t
= e1
->type
->toBasetype();
72 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
74 /* If e1 is not the 'this' pointer for ad
77 !(t
->ty
== Tpointer
&& t
->nextOf()->ty
== Tstruct
&&
78 ((TypeStruct
*)t
->nextOf())->sym
== ad
)
81 ((TypeStruct
*)t
)->sym
== ad
)
84 ClassDeclaration
*cd
= ad
->isClassDeclaration();
85 ClassDeclaration
*tcd
= t
->isClassHandle();
87 /* e1 is the right this if ad is a base class of e1
90 !(tcd
== cd
|| cd
->isBaseOf(tcd
, NULL
))
93 /* Only classes can be inner classes with an 'outer'
94 * member pointing to the enclosing class instance
96 if (tcd
&& tcd
->isNested())
98 /* e1 is the 'this' pointer for an inner class: tcd.
99 * Rewrite it as the 'this' pointer for the outer class.
102 e1
= new DotVarExp(loc
, e1
, tcd
->vthis
);
103 e1
->type
= tcd
->vthis
->type
;
104 e1
->type
= e1
->type
->addMod(t
->mod
);
105 // Do not call checkNestedRef()
106 //e1 = semantic(e1, sc);
108 // Skip up over nested functions, and get the enclosing
112 for (s
= tcd
->toParent();
113 s
&& s
->isFuncDeclaration();
116 FuncDeclaration
*f
= s
->isFuncDeclaration();
119 //printf("rewriting e1 to %s's this\n", f->toChars());
121 e1
= new VarExp(loc
, f
->vthis
);
125 e1
->error("need 'this' of type %s to access member %s"
126 " from static function %s",
127 ad
->toChars(), var
->toChars(), f
->toChars());
132 if (s
&& s
->isClassDeclaration())
134 e1
->type
= s
->isClassDeclaration()->type
;
135 e1
->type
= e1
->type
->addMod(t
->mod
);
137 e1
= semantic(e1
, sc
);
140 e1
= semantic(e1
, sc
);
144 /* Can't find a path from e1 to ad
148 e1
->error("this for %s needs to be type %s not type %s",
149 var
->toChars(), ad
->toChars(), t
->toChars());
150 return new ErrorExp();
156 /*****************************************
157 * Determine if 'this' is available.
158 * If it is, return the FuncDeclaration that has it.
161 FuncDeclaration
*hasThis(Scope
*sc
)
163 //printf("hasThis()\n");
164 Dsymbol
*p
= sc
->parent
;
165 while (p
&& p
->isTemplateMixin())
167 FuncDeclaration
*fdthis
= p
? p
->isFuncDeclaration() : NULL
;
168 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
170 // Go upwards until we find the enclosing member function
171 FuncDeclaration
*fd
= fdthis
;
181 Dsymbol
*parent
= fd
->parent
;
186 TemplateInstance
*ti
= parent
->isTemplateInstance();
192 fd
= parent
->isFuncDeclaration();
196 { //printf("test '%s'\n", fd->toChars());
204 return NULL
; // don't have 'this' available
207 bool isNeedThisScope(Scope
*sc
, Declaration
*d
)
209 if (sc
->intypeof
== 1)
212 AggregateDeclaration
*ad
= d
->isThis();
215 //printf("d = %s, ad = %s\n", d->toChars(), ad->toChars());
217 for (Dsymbol
*s
= sc
->parent
; s
; s
= s
->toParent2())
219 //printf("\ts = %s %s, toParent2() = %p\n", s->kind(), s->toChars(), s->toParent2());
220 if (AggregateDeclaration
*ad2
= s
->isAggregateDeclaration())
224 else if (ad2
->isNested())
229 if (FuncDeclaration
*f
= s
->isFuncDeclaration())
238 /***************************************
239 * Pull out any properties.
242 Expression
*resolvePropertiesX(Scope
*sc
, Expression
*e1
, Expression
*e2
= NULL
)
244 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
251 if (e1
->op
== TOKdot
)
253 DotExp
*de
= (DotExp
*)e1
;
254 if (de
->e2
->op
== TOKoverloadset
)
257 tthis
= de
->e1
->type
;
258 os
= ((OverExp
*)de
->e2
)->vars
;
262 else if (e1
->op
== TOKoverloadset
)
266 os
= ((OverExp
*)e1
)->vars
;
269 FuncDeclaration
*fd
= NULL
;
272 e2
= semantic(e2
, sc
);
273 if (e2
->op
== TOKerror
)
274 return new ErrorExp();
275 e2
= resolveProperties(sc
, e2
);
280 for (size_t i
= 0; i
< os
->a
.dim
; i
++)
282 FuncDeclaration
*f
= resolveFuncCall(loc
, sc
, os
->a
[i
], tiargs
, tthis
, &a
, 1);
286 return new ErrorExp();
288 assert(fd
->type
->ty
== Tfunction
);
293 Expression
*e
= new CallExp(loc
, e1
, e2
);
294 return semantic(e
, sc
);
298 for (size_t i
= 0; i
< os
->a
.dim
; i
++)
300 FuncDeclaration
*f
= resolveFuncCall(loc
, sc
, os
->a
[i
], tiargs
, tthis
, NULL
, 1);
304 return new ErrorExp();
306 assert(fd
->type
->ty
== Tfunction
);
307 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
308 if (!tf
->isref
&& e2
)
314 Expression
*e
= new CallExp(loc
, e1
);
316 e
= new AssignExp(loc
, e
, e2
);
317 return semantic(e
, sc
);
323 else if (e1
->op
== TOKdotti
)
325 DotTemplateInstanceExp
* dti
= (DotTemplateInstanceExp
*)e1
;
326 if (!dti
->findTempDecl(sc
))
328 if (!dti
->ti
->semanticTiargs(sc
))
330 tiargs
= dti
->ti
->tiargs
;
331 tthis
= dti
->e1
->type
;
332 if ((os
= dti
->ti
->tempdecl
->isOverloadSet()) != NULL
)
334 if ((s
= dti
->ti
->tempdecl
) != NULL
)
337 else if (e1
->op
== TOKdottd
)
339 DotTemplateExp
*dte
= (DotTemplateExp
*)e1
;
342 tthis
= dte
->e1
->type
;
345 else if (e1
->op
== TOKscope
)
347 s
= ((ScopeExp
*)e1
)->sds
;
348 TemplateInstance
*ti
= s
->isTemplateInstance();
349 if (ti
&& !ti
->semanticRun
&& ti
->tempdecl
)
351 //assert(ti->needsTypeInference(sc));
352 if (!ti
->semanticTiargs(sc
))
356 if ((os
= ti
->tempdecl
->isOverloadSet()) != NULL
)
358 if ((s
= ti
->tempdecl
) != NULL
)
362 else if (e1
->op
== TOKtemplate
)
364 s
= ((TemplateExp
*)e1
)->td
;
369 else if (e1
->op
== TOKdotvar
&& e1
->type
&& e1
->type
->toBasetype()->ty
== Tfunction
)
371 DotVarExp
*dve
= (DotVarExp
*)e1
;
372 s
= dve
->var
->isFuncDeclaration();
374 tthis
= dve
->e1
->type
;
377 else if (e1
->op
== TOKvar
&& e1
->type
&& e1
->type
->toBasetype()->ty
== Tfunction
)
379 s
= ((VarExp
*)e1
)->var
->isFuncDeclaration();
386 e2
= semantic(e2
, sc
);
387 if (e2
->op
== TOKerror
)
388 return new ErrorExp();
389 e2
= resolveProperties(sc
, e2
);
394 FuncDeclaration
*fd
= resolveFuncCall(loc
, sc
, s
, tiargs
, tthis
, &a
, 1);
398 return new ErrorExp();
399 assert(fd
->type
->ty
== Tfunction
);
400 Expression
*e
= new CallExp(loc
, e1
, e2
);
401 return semantic(e
, sc
);
405 FuncDeclaration
*fd
= resolveFuncCall(loc
, sc
, s
, tiargs
, tthis
, NULL
, 1);
409 return new ErrorExp();
410 assert(fd
->type
->ty
== Tfunction
);
411 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
412 if (!e2
|| tf
->isref
)
414 Expression
*e
= new CallExp(loc
, e1
);
416 e
= new AssignExp(loc
, e
, e2
);
417 return semantic(e
, sc
);
421 if (FuncDeclaration
*fd
= s
->isFuncDeclaration())
423 // Keep better diagnostic message for invalid property usage of functions
424 assert(fd
->type
->ty
== Tfunction
);
425 Expression
*e
= new CallExp(loc
, e1
, e2
);
426 return semantic(e
, sc
);
431 if (e1
->op
== TOKvar
)
433 VarExp
*ve
= (VarExp
*)e1
;
434 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
435 if (v
&& ve
->checkPurity(sc
, v
))
436 return new ErrorExp();
442 e1
->op
!= TOKtype
) // function type is not a property
444 /* Look for e1 being a lazy parameter; rewrite as delegate call
446 if (e1
->op
== TOKvar
)
448 VarExp
*ve
= (VarExp
*)e1
;
450 if (ve
->var
->storage_class
& STClazy
)
452 Expression
*e
= new CallExp(loc
, e1
);
453 return semantic(e
, sc
);
456 else if (e1
->op
== TOKdotvar
)
458 // Check for reading overlapped pointer field in @safe code.
459 if (checkUnsafeAccess(sc
, e1
, true, true))
460 return new ErrorExp();
462 else if (e1
->op
== TOKdot
)
464 e1
->error("expression has no value");
465 return new ErrorExp();
467 else if (e1
->op
== TOKcall
)
469 CallExp
*ce
= (CallExp
*)e1
;
470 // Check for reading overlapped pointer field in @safe code.
471 if (checkUnsafeAccess(sc
, ce
->e1
, true, true))
472 return new ErrorExp();
478 error(loc
, "cannot resolve type for %s", e1
->toChars());
484 error(loc
, "not a property %s", e1
->toChars());
485 return new ErrorExp();
488 error(loc
, "%s is not an lvalue", e1
->toChars());
489 return new ErrorExp();
492 Expression
*resolveProperties(Scope
*sc
, Expression
*e
)
494 //printf("resolveProperties(%s)\n", e->toChars());
496 e
= resolvePropertiesX(sc
, e
);
497 if (e
->checkRightThis(sc
))
498 return new ErrorExp();
502 /******************************
503 * Check the tail CallExp is really property function call.
505 static bool checkPropertyCall(Expression
*e
)
507 while (e
->op
== TOKcomma
)
508 e
= ((CommaExp
*)e
)->e2
;
510 if (e
->op
== TOKcall
)
512 CallExp
*ce
= (CallExp
*)e
;
516 tf
= (TypeFunction
*)ce
->f
->type
;
517 /* If a forward reference to ce->f, try to resolve it
519 if (!tf
->deco
&& ce
->f
->_scope
)
521 ce
->f
->semantic(ce
->f
->_scope
);
522 tf
= (TypeFunction
*)ce
->f
->type
;
525 else if (ce
->e1
->type
->ty
== Tfunction
)
526 tf
= (TypeFunction
*)ce
->e1
->type
;
527 else if (ce
->e1
->type
->ty
== Tdelegate
)
528 tf
= (TypeFunction
*)ce
->e1
->type
->nextOf();
529 else if (ce
->e1
->type
->ty
== Tpointer
&& ce
->e1
->type
->nextOf()->ty
== Tfunction
)
530 tf
= (TypeFunction
*)ce
->e1
->type
->nextOf();
537 /******************************
538 * If e1 is a property function (template), resolve it.
541 Expression
*resolvePropertiesOnly(Scope
*sc
, Expression
*e1
)
543 //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
546 TemplateDeclaration
*td
;
548 if (e1
->op
== TOKdot
)
550 DotExp
*de
= (DotExp
*)e1
;
551 if (de
->e2
->op
== TOKoverloadset
)
553 os
= ((OverExp
*)de
->e2
)->vars
;
557 else if (e1
->op
== TOKoverloadset
)
559 os
= ((OverExp
*)e1
)->vars
;
562 for (size_t i
= 0; i
< os
->a
.dim
; i
++)
564 Dsymbol
*s
= os
->a
[i
];
565 fd
= s
->isFuncDeclaration();
566 td
= s
->isTemplateDeclaration();
569 if (((TypeFunction
*)fd
->type
)->isproperty
)
570 return resolveProperties(sc
, e1
);
572 else if (td
&& td
->onemember
&&
573 (fd
= td
->onemember
->isFuncDeclaration()) != NULL
)
575 if (((TypeFunction
*)fd
->type
)->isproperty
||
576 (fd
->storage_class2
& STCproperty
) ||
577 (td
->_scope
->stc
& STCproperty
))
579 return resolveProperties(sc
, e1
);
584 else if (e1
->op
== TOKdotti
)
586 DotTemplateInstanceExp
* dti
= (DotTemplateInstanceExp
*)e1
;
587 if (dti
->ti
->tempdecl
&& (td
= dti
->ti
->tempdecl
->isTemplateDeclaration()) != NULL
)
590 else if (e1
->op
== TOKdottd
)
592 td
= ((DotTemplateExp
*)e1
)->td
;
595 else if (e1
->op
== TOKscope
)
597 Dsymbol
*s
= ((ScopeExp
*)e1
)->sds
;
598 TemplateInstance
*ti
= s
->isTemplateInstance();
599 if (ti
&& !ti
->semanticRun
&& ti
->tempdecl
)
601 if ((td
= ti
->tempdecl
->isTemplateDeclaration()) != NULL
)
605 else if (e1
->op
== TOKtemplate
)
607 td
= ((TemplateExp
*)e1
)->td
;
611 (fd
= td
->onemember
->isFuncDeclaration()) != NULL
)
613 if (((TypeFunction
*)fd
->type
)->isproperty
||
614 (fd
->storage_class2
& STCproperty
) ||
615 (td
->_scope
->stc
& STCproperty
))
617 return resolveProperties(sc
, e1
);
621 else if (e1
->op
== TOKdotvar
&& e1
->type
->ty
== Tfunction
)
623 DotVarExp
*dve
= (DotVarExp
*)e1
;
624 fd
= dve
->var
->isFuncDeclaration();
627 else if (e1
->op
== TOKvar
&& e1
->type
->ty
== Tfunction
&&
628 (sc
->intypeof
|| !((VarExp
*)e1
)->var
->needThis()))
630 fd
= ((VarExp
*)e1
)->var
->isFuncDeclaration();
633 if (((TypeFunction
*)fd
->type
)->isproperty
)
634 return resolveProperties(sc
, e1
);
640 // TODO: merge with Scope::search::searchScopes()
641 static Dsymbol
*searchScopes(Scope
*sc
, Loc loc
, Identifier
*ident
, int flags
)
644 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
648 if (scx
->scopesym
->isModule())
649 flags
|= SearchUnqualifiedModule
; // tell Module.search() that SearchLocalsOnly is to be obeyed
650 s
= scx
->scopesym
->search(loc
, ident
, flags
);
653 // overload set contains only module scope symbols.
654 if (s
->isOverloadSet())
656 // selective/renamed imports also be picked up
657 if (AliasDeclaration
*ad
= s
->isAliasDeclaration())
662 // See only module scope symbols for UFCS target.
663 Dsymbol
*p
= s
->toParent2();
664 if (p
&& p
->isModule())
669 // Stop when we hit a module, but keep going if that is not just under the global scope
670 if (scx
->scopesym
->isModule() && !(scx
->enclosing
&& !scx
->enclosing
->enclosing
))
676 /******************************
677 * Find symbol in accordance with the UFCS name look up rule
680 Expression
*searchUFCS(Scope
*sc
, UnaExp
*ue
, Identifier
*ident
)
682 //printf("searchUFCS(ident = %s)\n", ident->toChars());
687 if (sc
->flags
& SCOPEignoresymbolvisibility
)
688 flags
|= IgnoreSymbolVisibility
;
690 Dsymbol
*sold
= NULL
;
691 if (global
.params
.bug10378
|| global
.params
.check10378
)
693 sold
= searchScopes(sc
, loc
, ident
, flags
| IgnoreSymbolVisibility
);
694 if (!global
.params
.check10378
)
701 // First look in local scopes
702 s
= searchScopes(sc
, loc
, ident
, flags
| SearchLocalsOnly
);
705 // Second look in imported modules
706 s
= searchScopes(sc
, loc
, ident
, flags
| SearchImportsOnly
);
708 /** Still find private symbols, so that symbols that weren't access
709 * checked by the compiler remain usable. Once the deprecation is over,
710 * this should be moved to search_correct instead.
712 if (!s
&& !(flags
& IgnoreSymbolVisibility
))
714 s
= searchScopes(sc
, loc
, ident
, flags
| SearchLocalsOnly
| IgnoreSymbolVisibility
);
716 s
= searchScopes(sc
, loc
, ident
, flags
| SearchImportsOnly
| IgnoreSymbolVisibility
);
718 ::deprecation(loc
, "%s is not visible from module %s", s
->toPrettyChars(), sc
->_module
->toChars());
721 if (global
.params
.check10378
)
725 Scope::deprecation10378(loc
, sold
, snew
);
726 if (global
.params
.bug10378
)
732 return ue
->e1
->type
->Type::getProperty(loc
, ident
, 0);
734 FuncDeclaration
*f
= s
->isFuncDeclaration();
737 TemplateDeclaration
*td
= getFuncTemplateDecl(f
);
746 if (ue
->op
== TOKdotti
)
748 DotTemplateInstanceExp
*dti
= (DotTemplateInstanceExp
*)ue
;
749 TemplateInstance
*ti
= new TemplateInstance(loc
, s
->ident
);
750 ti
->tiargs
= dti
->ti
->tiargs
; // for better diagnostic message
751 if (!ti
->updateTempDecl(sc
, s
))
752 return new ErrorExp();
753 return new ScopeExp(loc
, ti
);
757 //printf("-searchUFCS() %s\n", s->toChars());
758 return new DsymbolExp(loc
, s
);
762 /******************************
763 * check e is exp.opDispatch!(tiargs) or not
764 * It's used to switch to UFCS the semantic analysis path
767 bool isDotOpDispatch(Expression
*e
)
769 return e
->op
== TOKdotti
&&
770 ((DotTemplateInstanceExp
*)e
)->ti
->name
== Id::opDispatch
;
773 /******************************
774 * Pull out callable entity with UFCS.
777 Expression
*resolveUFCS(Scope
*sc
, CallExp
*ce
)
783 if (ce
->e1
->op
== TOKdotid
)
785 DotIdExp
*die
= (DotIdExp
*)ce
->e1
;
786 Identifier
*ident
= die
->ident
;
788 Expression
*ex
= semanticX(die
, sc
);
796 Type
*t
= eleft
->type
->toBasetype();
797 if (t
->ty
== Tarray
|| t
->ty
== Tsarray
||
798 t
->ty
== Tnull
|| (t
->isTypeBasic() && t
->ty
!= Tvoid
))
800 /* Built-in types and arrays have no callable properties, so do shortcut.
801 * It is necessary in: e.init()
804 else if (t
->ty
== Taarray
)
806 if (ident
== Id::remove
)
809 * aa.remove(arg) into delete aa[arg]
811 if (!ce
->arguments
|| ce
->arguments
->dim
!= 1)
813 ce
->error("expected key as argument to aa.remove()");
814 return new ErrorExp();
816 if (!eleft
->type
->isMutable())
818 ce
->error("cannot remove key from %s associative array %s",
819 MODtoChars(t
->mod
), eleft
->toChars());
820 return new ErrorExp();
822 Expression
*key
= (*ce
->arguments
)[0];
823 key
= semantic(key
, sc
);
824 key
= resolveProperties(sc
, key
);
826 TypeAArray
*taa
= (TypeAArray
*)t
;
827 key
= key
->implicitCastTo(sc
, taa
->index
);
829 if (key
->checkValue())
830 return new ErrorExp();
832 semanticTypeInfo(sc
, taa
->index
);
834 return new RemoveExp(loc
, eleft
, key
);
839 if (Expression
*ey
= semanticY(die
, sc
, 1))
841 if (ey
->op
== TOKerror
)
844 if (isDotOpDispatch(ey
))
846 unsigned errors
= global
.startGagging();
847 e
= semantic(ce
->syntaxCopy(), sc
);
848 if (!global
.endGagging(errors
))
850 /* fall down to UFCS */
856 e
= searchUFCS(sc
, die
, ident
);
858 else if (ce
->e1
->op
== TOKdotti
)
860 DotTemplateInstanceExp
*dti
= (DotTemplateInstanceExp
*)ce
->e1
;
861 if (Expression
*ey
= semanticY(dti
, sc
, 1))
867 e
= searchUFCS(sc
, dti
, dti
->ti
->name
);
875 ce
->arguments
= new Expressions();
876 ce
->arguments
->shift(eleft
);
881 /******************************
882 * Pull out property with UFCS.
885 Expression
*resolveUFCSProperties(Scope
*sc
, Expression
*e1
, Expression
*e2
= NULL
)
891 if (e1
->op
== TOKdotid
)
893 DotIdExp
*die
= (DotIdExp
*)e1
;
895 e
= searchUFCS(sc
, die
, die
->ident
);
897 else if (e1
->op
== TOKdotti
)
899 DotTemplateInstanceExp
*dti
;
900 dti
= (DotTemplateInstanceExp
*)e1
;
902 e
= searchUFCS(sc
, dti
, dti
->ti
->name
);
913 // run semantic without gagging
914 e2
= semantic(e2
, sc
);
918 Expression
*ex
= e
->copy();
919 Expressions
*a1
= new Expressions();
922 ex
= new CallExp(loc
, ex
, a1
);
923 ex
= trySemantic(ex
, sc
);
927 Expressions
*a2
= new Expressions();
931 e
= new CallExp(loc
, e
, a2
);
933 { // if fallback setter exists, gag errors
934 e
= trySemantic(e
, sc
);
936 { checkPropertyCall(ex
);
937 ex
= new AssignExp(loc
, ex
, e2
);
938 return semantic(ex
, sc
);
942 { // strict setter prints errors if fails
945 checkPropertyCall(e
);
952 Expressions
*arguments
= new Expressions();
953 arguments
->setDim(1);
954 (*arguments
)[0] = eleft
;
955 e
= new CallExp(loc
, e
, arguments
);
957 checkPropertyCall(e
);
958 return semantic(e
, sc
);
962 /******************************
963 * Perform semantic() on an array of Expressions.
966 bool arrayExpressionSemantic(Expressions
*exps
, Scope
*sc
, bool preserveErrors
)
971 for (size_t i
= 0; i
< exps
->dim
; i
++)
973 Expression
*e
= (*exps
)[i
];
977 if (e
->op
== TOKerror
)
979 if (preserveErrors
|| e
->op
!= TOKerror
)
987 /****************************************
990 * exps aray of Expressions
992 * exps rewritten in place
995 void expandTuples(Expressions
*exps
)
997 //printf("expandTuples()\n");
1000 for (size_t i
= 0; i
< exps
->dim
; i
++)
1002 Expression
*arg
= (*exps
)[i
];
1006 // Look for tuple with 0 members
1007 if (arg
->op
== TOKtype
)
1009 TypeExp
*e
= (TypeExp
*)arg
;
1010 if (e
->type
->toBasetype()->ty
== Ttuple
)
1012 TypeTuple
*tt
= (TypeTuple
*)e
->type
->toBasetype();
1014 if (!tt
->arguments
|| tt
->arguments
->dim
== 0)
1025 // Inline expand all the tuples
1026 while (arg
->op
== TOKtuple
)
1028 TupleExp
*te
= (TupleExp
*)arg
;
1029 exps
->remove(i
); // remove arg
1030 exps
->insert(i
, te
->exps
); // replace with tuple contents
1032 return; // empty tuple, no more arguments
1033 (*exps
)[i
] = Expression::combine(te
->e0
, (*exps
)[i
]);
1040 /****************************************
1041 * Expand alias this tuples.
1044 TupleDeclaration
*isAliasThisTuple(Expression
*e
)
1049 Type
*t
= e
->type
->toBasetype();
1051 if (Dsymbol
*s
= t
->toDsymbol(NULL
))
1053 AggregateDeclaration
*ad
= s
->isAggregateDeclaration();
1057 if (s
&& s
->isVarDeclaration())
1059 TupleDeclaration
*td
= s
->isVarDeclaration()->toAlias()->isTupleDeclaration();
1060 if (td
&& td
->isexp
)
1063 if (Type
*att
= t
->aliasthisOf())
1073 int expandAliasThisTuples(Expressions
*exps
, size_t starti
)
1075 if (!exps
|| exps
->dim
== 0)
1078 for (size_t u
= starti
; u
< exps
->dim
; u
++)
1080 Expression
*exp
= (*exps
)[u
];
1081 TupleDeclaration
*td
= isAliasThisTuple(exp
);
1085 for (size_t i
= 0; i
<td
->objects
->dim
; ++i
)
1087 Expression
*e
= isExpression((*td
->objects
)[i
]);
1089 assert(e
->op
== TOKdsymbol
);
1090 DsymbolExp
*se
= (DsymbolExp
*)e
;
1091 Declaration
*d
= se
->s
->isDeclaration();
1093 e
= new DotVarExp(exp
->loc
, exp
, d
);
1096 exps
->insert(u
+ i
, e
);
1105 /****************************************
1106 * The common type is determined by applying ?: to each pair.
1108 * exps[] properties resolved, implicitly cast to common type, rewritten in place
1109 * *pt if pt is not NULL, set to the common type
1111 * true a semantic error was detected
1114 bool arrayExpressionToCommonType(Scope
*sc
, Expressions
*exps
, Type
**pt
)
1116 /* Still have a problem with:
1117 * ubyte[][] = [ cast(ubyte[])"hello", [1]];
1118 * which works if the array literal is initialized top down with the ubyte[][]
1119 * type, but fails with this function doing bottom up typing.
1121 //printf("arrayExpressionToCommonType()\n");
1122 IntegerExp
integerexp(0);
1123 CondExp
condexp(Loc(), &integerexp
, NULL
, NULL
);
1126 Expression
*e0
= NULL
; // dead-store to prevent spurious warning
1127 size_t j0
= ~0; // dead-store to prevent spurious warning
1128 for (size_t i
= 0; i
< exps
->dim
; i
++)
1130 Expression
*e
= (*exps
)[i
];
1134 e
= resolveProperties(sc
, e
);
1137 e
->error("%s has no value", e
->toChars());
1141 if (e
->op
== TOKtype
)
1143 e
->checkValue(); // report an error "type T has no value"
1147 if (e
->type
->ty
== Tvoid
)
1149 // void expressions do not concur to the determination of the common
1153 if (checkNonAssignmentArrayOp(e
))
1159 e
= doCopyOrMove(sc
, e
);
1161 if (t0
&& !t0
->equals(e
->type
))
1163 /* This applies ?: to merge the types. It's backwards;
1164 * ?: should call this function to merge types.
1166 condexp
.type
= NULL
;
1169 condexp
.loc
= e
->loc
;
1170 Expression
*ex
= semantic(&condexp
, sc
);
1171 if (ex
->op
== TOKerror
)
1175 (*exps
)[j0
] = condexp
.e1
;
1182 if (e
->op
!= TOKerror
)
1187 t0
= Type::tvoid
; // [] is typed as void[]
1188 else if (t0
->ty
!= Terror
)
1190 for (size_t i
= 0; i
< exps
->dim
; i
++)
1192 Expression
*e
= (*exps
)[i
];
1196 e
= e
->implicitCastTo(sc
, t0
);
1197 //assert(e->op != TOKerror);
1198 if (e
->op
== TOKerror
)
1200 /* Bugzilla 13024: a workaround for the bug in typeMerge -
1201 * it should paint e1 and e2 by deduced common type,
1202 * but doesn't in this particular case.
1213 return (t0
== Type::terror
);
1216 /****************************************
1217 * Get TemplateDeclaration enclosing FuncDeclaration.
1220 TemplateDeclaration
*getFuncTemplateDecl(Dsymbol
*s
)
1222 FuncDeclaration
*f
= s
->isFuncDeclaration();
1225 TemplateInstance
*ti
= f
->parent
->isTemplateInstance();
1226 if (ti
&& !ti
->isTemplateMixin() &&
1227 ti
->tempdecl
&& ((TemplateDeclaration
*)ti
->tempdecl
)->onemember
&&
1228 ti
->tempdecl
->ident
== f
->ident
)
1230 return (TemplateDeclaration
*)ti
->tempdecl
;
1236 /************************************************
1237 * If we want the value of this expression, but do not want to call
1238 * the destructor on it.
1241 Expression
*valueNoDtor(Expression
*e
)
1243 if (e
->op
== TOKcall
)
1245 /* The struct value returned from the function is transferred
1246 * so do not call the destructor on it.
1248 * ((S _ctmp = S.init), _ctmp).this(...)
1249 * and make sure the destructor is not called on _ctmp
1250 * BUG: if e is a CommaExp, we should go down the right side.
1252 CallExp
*ce
= (CallExp
*)e
;
1253 if (ce
->e1
->op
== TOKdotvar
)
1255 DotVarExp
*dve
= (DotVarExp
*)ce
->e1
;
1256 if (dve
->var
->isCtorDeclaration())
1258 // It's a constructor call
1259 if (dve
->e1
->op
== TOKcomma
)
1261 CommaExp
*comma
= (CommaExp
*)dve
->e1
;
1262 if (comma
->e2
->op
== TOKvar
)
1264 VarExp
*ve
= (VarExp
*)comma
->e2
;
1265 VarDeclaration
*ctmp
= ve
->var
->isVarDeclaration();
1268 ctmp
->storage_class
|= STCnodtor
;
1269 assert(!ce
->isLvalue());
1276 else if (e
->op
== TOKvar
)
1278 VarDeclaration
*vtmp
= ((VarExp
*)e
)->var
->isVarDeclaration();
1279 if (vtmp
&& vtmp
->storage_class
& STCrvalue
)
1281 vtmp
->storage_class
|= STCnodtor
;
1287 /********************************************
1288 * Issue an error if default construction is disabled for type t.
1289 * Default construction is required for arrays and 'out' parameters.
1291 * true an error was issued
1293 bool checkDefCtor(Loc loc
, Type
*t
)
1295 t
= t
->baseElemOf();
1296 if (t
->ty
== Tstruct
)
1298 StructDeclaration
*sd
= ((TypeStruct
*)t
)->sym
;
1299 if (sd
->noDefaultCtor
)
1301 sd
->error(loc
, "default construction is disabled");
1308 /*********************************************
1309 * If e is an instance of a struct, and that struct has a copy constructor,
1313 * sc just used to specify the scope of created temporary variable
1315 Expression
*callCpCtor(Scope
*sc
, Expression
*e
)
1317 Type
*tv
= e
->type
->baseElemOf();
1318 if (tv
->ty
== Tstruct
)
1320 StructDeclaration
*sd
= ((TypeStruct
*)tv
)->sym
;
1323 /* Create a variable tmp, and replace the argument e with:
1325 * and let AssignExp() handle the construction.
1326 * This is not the most efficent, ideally tmp would be constructed
1327 * directly onto the stack.
1329 VarDeclaration
*tmp
= copyToTemp(STCrvalue
, "__copytmp", e
);
1330 tmp
->storage_class
|= STCnodtor
;
1332 Expression
*de
= new DeclarationExp(e
->loc
, tmp
);
1333 Expression
*ve
= new VarExp(e
->loc
, tmp
);
1334 de
->type
= Type::tvoid
;
1336 e
= Expression::combine(de
, ve
);
1342 /************************************************
1343 * Handle the postblit call on lvalue, or the move of rvalue.
1345 Expression
*doCopyOrMove(Scope
*sc
, Expression
*e
)
1347 if (e
->op
== TOKquestion
)
1349 CondExp
*ce
= (CondExp
*)e
;
1350 ce
->e1
= doCopyOrMove(sc
, ce
->e1
);
1351 ce
->e2
= doCopyOrMove(sc
, ce
->e2
);
1355 e
= e
->isLvalue() ? callCpCtor(sc
, e
) : valueNoDtor(e
);
1360 /****************************************
1361 * Now that we know the exact type of the function we're calling,
1362 * the arguments[] need to be adjusted:
1363 * 1. implicitly convert argument to the corresponding parameter type
1364 * 2. add default arguments for any missing arguments
1365 * 3. do default promotions on arguments corresponding to ...
1366 * 4. add hidden _arguments[] argument
1367 * 5. call copy constructor for struct value arguments
1369 * tf type of the function
1370 * fd the function being called, NULL if called indirectly
1372 * *prettype return type of function
1373 * *peprefix expression to execute before arguments[] are evaluated, NULL if none
1375 * true errors happened
1378 bool functionParameters(Loc loc
, Scope
*sc
, TypeFunction
*tf
,
1379 Type
*tthis
, Expressions
*arguments
, FuncDeclaration
*fd
, Type
**prettype
, Expression
**peprefix
)
1381 //printf("functionParameters()\n");
1383 assert(fd
|| tf
->next
);
1384 size_t nargs
= arguments
? arguments
->dim
: 0;
1385 size_t nparams
= Parameter::dim(tf
->parameters
);
1386 unsigned olderrors
= global
.errors
;
1388 *prettype
= Type::terror
;
1389 Expression
*eprefix
= NULL
;
1392 if (nargs
> nparams
&& tf
->varargs
== 0)
1394 error(loc
, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong
)nparams
, (ulonglong
)nargs
, tf
->toChars());
1398 // If inferring return type, and semantic3() needs to be run if not already run
1399 if (!tf
->next
&& fd
->inferRetType
)
1401 fd
->functionSemantic();
1403 else if (fd
&& fd
->parent
)
1405 TemplateInstance
*ti
= fd
->parent
->isTemplateInstance();
1406 if (ti
&& ti
->tempdecl
)
1408 fd
->functionSemantic3();
1411 bool isCtorCall
= fd
&& fd
->needThis() && fd
->isCtorDeclaration();
1413 size_t n
= (nargs
> nparams
) ? nargs
: nparams
; // n = max(nargs, nparams)
1415 /* If the function return type has wildcards in it, we'll need to figure out the actual type
1416 * based on the actual argument types.
1419 if (tthis
&& tf
->isWild() && !isCtorCall
)
1422 if (t
->isImmutable())
1423 wildmatch
= MODimmutable
;
1424 else if (t
->isWildConst())
1425 wildmatch
= MODwildconst
;
1426 else if (t
->isWild())
1427 wildmatch
= MODwild
;
1428 else if (t
->isConst())
1429 wildmatch
= MODconst
;
1431 wildmatch
= MODmutable
;
1435 for (size_t i
= 0; i
< n
; i
++)
1440 arg
= (*arguments
)[i
];
1446 Parameter
*p
= Parameter::getNth(tf
->parameters
, i
);
1452 if (tf
->varargs
== 2 && i
+ 1 == nparams
)
1454 error(loc
, "expected %llu function arguments, not %llu", (ulonglong
)nparams
, (ulonglong
)nargs
);
1457 arg
= p
->defaultArg
;
1458 arg
= inlineCopy(arg
, sc
);
1459 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1460 arg
= arg
->resolveLoc(loc
, sc
);
1461 arguments
->push(arg
);
1465 if (tf
->varargs
== 2 && i
+ 1 == nparams
)
1467 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
1470 if ((m
= arg
->implicitConvTo(p
->type
)) > MATCHnomatch
)
1472 if (p
->type
->nextOf() && arg
->implicitConvTo(p
->type
->nextOf()) >= m
)
1474 else if (nargs
!= nparams
)
1475 { error(loc
, "expected %llu function arguments, not %llu", (ulonglong
)nparams
, (ulonglong
)nargs
);
1482 Type
*tb
= p
->type
->toBasetype();
1483 Type
*tret
= p
->isLazyArray();
1489 /* Create a static array variable v of type arg->type:
1490 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1492 * The array literal in the initializer of the hidden variable
1493 * is now optimized. See Bugzilla 2356.
1495 Type
*tbn
= ((TypeArray
*)tb
)->next
;
1496 Type
*tsa
= tbn
->sarrayOf(nargs
- i
);
1498 Expressions
*elements
= new Expressions();
1499 elements
->setDim(nargs
- i
);
1500 for (size_t u
= 0; u
< elements
->dim
; u
++)
1502 Expression
*a
= (*arguments
)[i
+ u
];
1503 if (tret
&& a
->implicitConvTo(tret
))
1505 a
= a
->implicitCastTo(sc
, tret
);
1506 a
= a
->optimize(WANTvalue
);
1507 a
= toDelegate(a
, a
->type
, sc
);
1510 a
= a
->implicitCastTo(sc
, tbn
);
1513 // Bugzilla 14395: Convert to a static array literal, or its slice.
1514 arg
= new ArrayLiteralExp(loc
, elements
);
1516 if (tb
->ty
== Tarray
)
1518 arg
= new SliceExp(loc
, arg
, NULL
, NULL
);
1519 arg
->type
= p
->type
;
1526 * new Tclass(arg0, arg1, ..., argn)
1528 Expressions
*args
= new Expressions();
1529 args
->setDim(nargs
- i
);
1530 for (size_t u
= i
; u
< nargs
; u
++)
1531 (*args
)[u
- i
] = (*arguments
)[u
];
1532 arg
= new NewExp(loc
, NULL
, NULL
, p
->type
, args
);
1538 error(loc
, "not enough arguments");
1543 arg
= semantic(arg
, sc
);
1544 //printf("\targ = '%s'\n", arg->toChars());
1545 arguments
->setDim(i
+ 1);
1546 (*arguments
)[i
] = arg
;
1552 if (!(p
->storageClass
& STClazy
&& p
->type
->ty
== Tvoid
))
1554 bool isRef
= (p
->storageClass
& (STCref
| STCout
)) != 0;
1555 if (unsigned char wm
= arg
->type
->deduceWild(p
->type
, isRef
))
1558 wildmatch
= MODmerge(wildmatch
, wm
);
1561 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
1568 if ((wildmatch
== MODmutable
|| wildmatch
== MODimmutable
) &&
1569 tf
->next
->hasWild() &&
1570 (tf
->isref
|| !tf
->next
->implicitConvTo(tf
->next
->immutableOf())))
1574 /* If the called function may return the reference to
1575 * outer inout data, it should be rejected.
1577 * void foo(ref inout(int) x) {
1578 * ref inout(int) bar(inout(int)) { return x; }
1579 * struct S { ref inout(int) bar() inout { return x; } }
1580 * bar(int.init) = 1; // bad!
1581 * S().bar() = 1; // bad!
1585 if (fd
->isThis() || fd
->isNested())
1586 s
= fd
->toParent2();
1587 for (; s
; s
= s
->toParent2())
1589 if (AggregateDeclaration
*ad
= s
->isAggregateDeclaration())
1595 if (FuncDeclaration
*ff
= s
->isFuncDeclaration())
1597 if (((TypeFunction
*)ff
->type
)->iswild
)
1600 if (ff
->isNested() || ff
->isThis())
1606 else if (tf
->isWild())
1609 const char *s
= wildmatch
== MODmutable
? "mutable" : MODtoChars(wildmatch
);
1610 error(loc
, "modify inout to %s is not allowed inside inout function", s
);
1615 assert(nargs
>= nparams
);
1616 for (size_t i
= 0; i
< nargs
; i
++)
1618 Expression
*arg
= (*arguments
)[i
];
1622 Parameter
*p
= Parameter::getNth(tf
->parameters
, i
);
1624 if (!(p
->storageClass
& STClazy
&& p
->type
->ty
== Tvoid
))
1626 Type
*tprm
= p
->type
;
1627 if (p
->type
->hasWild())
1628 tprm
= p
->type
->substWildTo(wildmatch
);
1629 if (!tprm
->equals(arg
->type
))
1631 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
1632 arg
= arg
->implicitCastTo(sc
, tprm
);
1633 arg
= arg
->optimize(WANTvalue
, (p
->storageClass
& (STCref
| STCout
)) != 0);
1636 if (p
->storageClass
& STCref
)
1638 arg
= arg
->toLvalue(sc
, arg
);
1640 // Look for mutable misaligned pointer, etc., in @safe mode
1641 err
|= checkUnsafeAccess(sc
, arg
, false, true);
1643 else if (p
->storageClass
& STCout
)
1645 Type
*t
= arg
->type
;
1646 if (!t
->isMutable() || !t
->isAssignable()) // check blit assignable
1648 arg
->error("cannot modify struct %s with immutable members", arg
->toChars());
1653 // Look for misaligned pointer, etc., in @safe mode
1654 err
|= checkUnsafeAccess(sc
, arg
, false, true);
1655 err
|= checkDefCtor(arg
->loc
, t
); // t must be default constructible
1657 arg
= arg
->toLvalue(sc
, arg
);
1659 else if (p
->storageClass
& STClazy
)
1661 // Convert lazy argument to a delegate
1662 if (p
->type
->ty
== Tvoid
)
1663 arg
= toDelegate(arg
, p
->type
, sc
);
1665 arg
= toDelegate(arg
, arg
->type
, sc
);
1668 //printf("arg: %s\n", arg->toChars());
1669 //printf("type: %s\n", arg->type->toChars());
1670 if (tf
->parameterEscapes(p
))
1672 /* Argument value can escape from the called function.
1673 * Check arg to see if it matters.
1675 if (global
.params
.vsafe
)
1676 err
|= checkParamArgumentEscape(sc
, fd
, p
->ident
, arg
, false);
1680 /* Argument value cannot escape from the called function.
1682 Expression
*a
= arg
;
1683 if (a
->op
== TOKcast
)
1684 a
= ((CastExp
*)a
)->e1
;
1686 if (a
->op
== TOKfunction
)
1688 /* Function literals can only appear once, so if this
1689 * appearance was scoped, there cannot be any others.
1691 FuncExp
*fe
= (FuncExp
*)a
;
1692 fe
->fd
->tookAddressOf
= 0;
1694 else if (a
->op
== TOKdelegate
)
1696 /* For passing a delegate to a scoped parameter,
1697 * this doesn't count as taking the address of it.
1698 * We only worry about 'escaping' references to the function.
1700 DelegateExp
*de
= (DelegateExp
*)a
;
1701 if (de
->e1
->op
== TOKvar
)
1702 { VarExp
*ve
= (VarExp
*)de
->e1
;
1703 FuncDeclaration
*f
= ve
->var
->isFuncDeclaration();
1705 { f
->tookAddressOf
--;
1706 //printf("tookAddressOf = %d\n", f->tookAddressOf);
1711 arg
= arg
->optimize(WANTvalue
, (p
->storageClass
& (STCref
| STCout
)) != 0);
1715 // These will be the trailing ... arguments
1717 // If not D linkage, do promotions
1718 if (tf
->linkage
!= LINKd
)
1720 // Promote bytes, words, etc., to ints
1721 arg
= integralPromotions(arg
, sc
);
1723 // Promote floats to doubles
1724 switch (arg
->type
->ty
)
1727 arg
= arg
->castTo(sc
, Type::tfloat64
);
1731 arg
= arg
->castTo(sc
, Type::timaginary64
);
1735 if (tf
->varargs
== 1)
1737 const char *p
= tf
->linkage
== LINKc
? "extern(C)" : "extern(C++)";
1738 if (arg
->type
->ty
== Tarray
)
1740 arg
->error("cannot pass dynamic arrays to %s vararg functions", p
);
1743 if (arg
->type
->ty
== Tsarray
)
1745 arg
->error("cannot pass static arrays to %s vararg functions", p
);
1751 // Do not allow types that need destructors
1752 if (arg
->type
->needsDestruction())
1754 arg
->error("cannot pass types that need destruction as variadic arguments");
1758 // Convert static arrays to dynamic arrays
1759 // BUG: I don't think this is right for D2
1760 Type
*tb
= arg
->type
->toBasetype();
1761 if (tb
->ty
== Tsarray
)
1763 TypeSArray
*ts
= (TypeSArray
*)tb
;
1764 Type
*ta
= ts
->next
->arrayOf();
1765 if (ts
->size(arg
->loc
) == 0)
1766 arg
= new NullExp(arg
->loc
, ta
);
1768 arg
= arg
->castTo(sc
, ta
);
1770 if (tb
->ty
== Tstruct
)
1772 //arg = callCpCtor(sc, arg);
1775 // Give error for overloaded function addresses
1776 if (arg
->op
== TOKsymoff
)
1777 { SymOffExp
*se
= (SymOffExp
*)arg
;
1778 if (se
->hasOverloads
&&
1779 !se
->var
->isFuncDeclaration()->isUnique())
1780 { arg
->error("function %s is overloaded", arg
->toChars());
1784 if (arg
->checkValue())
1786 arg
= arg
->optimize(WANTvalue
);
1788 (*arguments
)[i
] = arg
;
1791 /* Remaining problems:
1792 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
1793 * implemented by calling a function) we'll defer this for now.
1794 * 2. value structs (or static arrays of them) that need to be copy constructed
1795 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
1796 * function gets called (functions normally destroy their parameters)
1797 * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
1798 * up properly. Pushing arguments on the stack then cannot fail.
1802 /* TODO: tackle problem 1)
1804 const bool leftToRight
= true; // TODO: something like !fd.isArrayOp
1806 assert(nargs
== nparams
); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
1808 const ptrdiff_t start
= (leftToRight
? 0 : (ptrdiff_t)nargs
- 1);
1809 const ptrdiff_t end
= (leftToRight
? (ptrdiff_t)nargs
: -1);
1810 const ptrdiff_t step
= (leftToRight
? 1 : -1);
1812 /* Compute indices of last throwing argument and first arg needing destruction.
1813 * Used to not set up destructors unless an arg needs destruction on a throw
1814 * in a later argument.
1816 ptrdiff_t lastthrow
= -1;
1817 ptrdiff_t firstdtor
= -1;
1818 for (ptrdiff_t i
= start
; i
!= end
; i
+= step
)
1820 Expression
*arg
= (*arguments
)[i
];
1821 if (canThrow(arg
, sc
->func
, false))
1823 if (firstdtor
== -1 && arg
->type
->needsDestruction())
1825 Parameter
*p
= (i
>= (ptrdiff_t)nparams
? NULL
: Parameter::getNth(tf
->parameters
, i
));
1826 if (!(p
&& (p
->storageClass
& (STClazy
| STCref
| STCout
))))
1831 /* Does problem 3) apply to this call?
1833 const bool needsPrefix
= (firstdtor
>= 0 && lastthrow
>= 0
1834 && (lastthrow
- firstdtor
) * step
> 0);
1836 /* If so, initialize 'eprefix' by declaring the gate
1838 VarDeclaration
*gate
= NULL
;
1841 // eprefix => bool __gate [= false]
1842 Identifier
*idtmp
= Identifier::generateId("__gate");
1843 gate
= new VarDeclaration(loc
, Type::tbool
, idtmp
, NULL
);
1844 gate
->storage_class
|= STCtemp
| STCctfe
| STCvolatile
;
1847 Expression
*ae
= new DeclarationExp(loc
, gate
);
1848 eprefix
= semantic(ae
, sc
);
1851 for (ptrdiff_t i
= start
; i
!= end
; i
+= step
)
1853 Expression
*arg
= (*arguments
)[i
];
1855 Parameter
*parameter
= (i
>= (ptrdiff_t)nparams
? NULL
: Parameter::getNth(tf
->parameters
, i
));
1856 const bool isRef
= (parameter
&& (parameter
->storageClass
& (STCref
| STCout
)));
1857 const bool isLazy
= (parameter
&& (parameter
->storageClass
& STClazy
));
1859 /* Skip lazy parameters
1864 /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
1865 * Declare a temporary variable for this arg and append that declaration to 'eprefix',
1866 * which will implicitly take care of potential problem 2) for this arg.
1867 * 'eprefix' will therefore finally contain all args up to and including the last
1868 * potentially throwing arg, excluding all lazy parameters.
1872 const bool needsDtor
= (!isRef
&& arg
->type
->needsDestruction() && i
!= lastthrow
);
1874 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
1876 VarDeclaration
*tmp
= copyToTemp(0,
1877 needsDtor
? "__pfx" : "__pfy",
1878 !isRef
? arg
: arg
->addressOf());
1881 /* Modify the destructor so it only runs if gate==false, i.e.,
1882 * only if there was a throw while constructing the args
1888 assert(i
== lastthrow
);
1894 // edtor => (__gate || edtor)
1896 Expression
*e
= tmp
->edtor
;
1897 e
= new OrOrExp(e
->loc
, new VarExp(e
->loc
, gate
), e
);
1898 tmp
->edtor
= semantic(e
, sc
);
1899 //printf("edtor: %s\n", tmp->edtor->toChars());
1902 // eprefix => (eprefix, auto __pfx/y = arg)
1903 DeclarationExp
*ae
= new DeclarationExp(loc
, tmp
);
1904 eprefix
= Expression::combine(eprefix
, semantic(ae
, sc
));
1907 arg
= new VarExp(loc
, tmp
);
1908 arg
= semantic(arg
, sc
);
1911 arg
= new PtrExp(loc
, arg
);
1912 arg
= semantic(arg
, sc
);
1915 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
1916 * i.e., disable the dtors right after constructing the last throwing arg.
1917 * From now on, the callee will take care of destructing the args because
1918 * the args are implicitly moved into function parameters.
1920 * Set gate to null to let the next iterations know they don't need to
1921 * append to eprefix anymore.
1925 Expression
*e
= new AssignExp(gate
->loc
, new VarExp(gate
->loc
, gate
), new IntegerExp(gate
->loc
, 1, Type::tbool
));
1926 eprefix
= Expression::combine(eprefix
, semantic(e
, sc
));
1932 /* No gate, no prefix to append to.
1933 * Handle problem 2) by calling the copy constructor for value structs
1934 * (or static arrays of them) if appropriate.
1936 Type
*tv
= arg
->type
->baseElemOf();
1937 if (!isRef
&& tv
->ty
== Tstruct
)
1938 arg
= doCopyOrMove(sc
, arg
);
1941 (*arguments
)[i
] = arg
;
1944 //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
1946 // If D linkage and variadic, add _arguments[] as first argument
1947 if (tf
->linkage
== LINKd
&& tf
->varargs
== 1)
1949 assert(arguments
->dim
>= nparams
);
1951 Parameters
*args
= new Parameters
;
1952 args
->setDim(arguments
->dim
- nparams
);
1953 for (size_t i
= 0; i
< arguments
->dim
- nparams
; i
++)
1955 Parameter
*arg
= new Parameter(STCin
, (*arguments
)[nparams
+ i
]->type
, NULL
, NULL
);
1959 TypeTuple
*tup
= new TypeTuple(args
);
1960 Expression
*e
= new TypeidExp(loc
, tup
);
1961 e
= semantic(e
, sc
);
1962 arguments
->insert(0, e
);
1965 Type
*tret
= tf
->next
;
1968 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
1969 // wildmatch, tf->isWild(), fd->isolateReturn());
1972 assert(sc
->intypeof
|| global
.errors
);
1973 tthis
= fd
->isThis()->type
->addMod(fd
->type
->mod
);
1975 if (tf
->isWild() && !fd
->isolateReturn())
1978 tret
= tret
->substWildTo(wildmatch
);
1980 if (!tret
->implicitConvTo(tthis
) &&
1981 !(MODimplicitConv(tret
->mod
, tthis
->mod
) && tret
->isBaseOf(tthis
, &offset
) && offset
== 0))
1983 const char* s1
= tret
->isNaked() ? " mutable" : tret
->modToChars();
1984 const char* s2
= tthis
->isNaked() ? " mutable" : tthis
->modToChars();
1985 ::error(loc
, "inout constructor %s creates%s object, not%s",
1986 fd
->toPrettyChars(), s1
, s2
);
1992 else if (wildmatch
&& tret
)
1994 /* Adjust function return type based on wildmatch
1996 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
1997 tret
= tret
->substWildTo(wildmatch
);
2000 *peprefix
= eprefix
;
2001 return (err
|| olderrors
!= global
.errors
);
2004 /******************************** Expression **************************/
2006 Expression::Expression(Loc loc
, TOK op
, int size
)
2008 //printf("Expression::Expression(op = %d) this = %p\n", op, this);
2011 this->size
= (unsigned char)size
;
2016 void Expression::_init()
2018 CTFEExp::cantexp
= new CTFEExp(TOKcantexp
);
2019 CTFEExp::voidexp
= new CTFEExp(TOKvoidexp
);
2020 CTFEExp::breakexp
= new CTFEExp(TOKbreak
);
2021 CTFEExp::continueexp
= new CTFEExp(TOKcontinue
);
2022 CTFEExp::gotoexp
= new CTFEExp(TOKgoto
);
2025 Expression
*Expression::syntaxCopy()
2027 //printf("Expression::syntaxCopy()\n");
2032 /*********************************
2033 * Does *not* do a deep copy.
2036 Expression
*Expression::copy()
2043 void *pe
= mem
.xmalloc(size
);
2044 //printf("Expression::copy(op = %d) e = %p\n", op, pe);
2045 e
= (Expression
*)memcpy(pe
, (void *)this, size
);
2049 void Expression::print()
2051 fprintf(stderr
, "%s\n", toChars());
2055 const char *Expression::toChars()
2059 toCBuffer(this, &buf
, &hgs
);
2060 return buf
.extractString();
2063 void Expression::error(const char *format
, ...) const
2065 if (type
!= Type::terror
)
2068 va_start(ap
, format
);
2069 ::verror(loc
, format
, ap
);
2074 void Expression::warning(const char *format
, ...) const
2076 if (type
!= Type::terror
)
2079 va_start(ap
, format
);
2080 ::vwarning(loc
, format
, ap
);
2085 void Expression::deprecation(const char *format
, ...) const
2087 if (type
!= Type::terror
)
2090 va_start(ap
, format
);
2091 ::vdeprecation(loc
, format
, ap
);
2096 /**********************************
2097 * Combine e1 and e2 by CommaExp if both are not NULL.
2099 Expression
*Expression::combine(Expression
*e1
, Expression
*e2
)
2105 e1
= new CommaExp(e1
->loc
, e1
, e2
);
2106 e1
->type
= e2
->type
;
2114 /**********************************
2115 * If 'e' is a tree of commas, returns the leftmost expression
2116 * by stripping off it from the tree. The remained part of the tree
2117 * is returned via *pe0.
2118 * Otherwise 'e' is directly returned and *pe0 is set to NULL.
2120 Expression
*Expression::extractLast(Expression
*e
, Expression
**pe0
)
2122 if (e
->op
!= TOKcomma
)
2128 CommaExp
*ce
= (CommaExp
*)e
;
2129 if (ce
->e2
->op
!= TOKcomma
)
2138 Expression
**pce
= &ce
->e2
;
2139 while (((CommaExp
*)(*pce
))->e2
->op
== TOKcomma
)
2141 pce
= &((CommaExp
*)(*pce
))->e2
;
2143 assert((*pce
)->op
== TOKcomma
);
2144 ce
= (CommaExp
*)(*pce
);
2151 dinteger_t
Expression::toInteger()
2153 //printf("Expression %s\n", Token::toChars(op));
2154 error("integer constant expression expected instead of %s", toChars());
2158 uinteger_t
Expression::toUInteger()
2160 //printf("Expression %s\n", Token::toChars(op));
2161 return (uinteger_t
)toInteger();
2164 real_t
Expression::toReal()
2166 error("floating point constant expression expected instead of %s", toChars());
2167 return CTFloat::zero
;
2170 real_t
Expression::toImaginary()
2172 error("floating point constant expression expected instead of %s", toChars());
2173 return CTFloat::zero
;
2176 complex_t
Expression::toComplex()
2178 error("floating point constant expression expected instead of %s", toChars());
2179 return complex_t(CTFloat::zero
);
2182 StringExp
*Expression::toStringExp()
2187 /***************************************
2188 * Return !=0 if expression is an lvalue.
2191 bool Expression::isLvalue()
2196 /*******************************
2197 * Give error if we're not an lvalue.
2198 * If we can, convert expression to be an lvalue.
2201 Expression
*Expression::toLvalue(Scope
*, Expression
*e
)
2205 else if (!loc
.filename
)
2208 if (e
->op
== TOKtype
)
2209 error("%s '%s' is a type, not an lvalue", e
->type
->kind(), e
->type
->toChars());
2211 error("%s is not an lvalue", e
->toChars());
2213 return new ErrorExp();
2216 /***************************************
2219 * flag: 1: do not issue error message for invalid modification
2221 * 0: is not modifiable
2222 * 1: is modifiable in default == being related to type->isMutable()
2223 * 2: is modifiable, because this is a part of initializing.
2226 int Expression::checkModifiable(Scope
*, int)
2228 return type
? 1 : 0; // default modifiable
2231 Expression
*Expression::modifiableLvalue(Scope
*sc
, Expression
*e
)
2233 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
2235 // See if this expression is a modifiable lvalue (i.e. not const)
2236 if (checkModifiable(sc
) == 1)
2239 if (!type
->isMutable())
2241 error("cannot modify %s expression %s", MODtoChars(type
->mod
), toChars());
2242 return new ErrorExp();
2244 else if (!type
->isAssignable())
2246 error("cannot modify struct %s %s with immutable members", toChars(), type
->toChars());
2247 return new ErrorExp();
2250 return toLvalue(sc
, e
);
2253 /****************************************
2254 * Check that the expression has a valid type.
2255 * If not, generates an error "... has no type".
2257 * true if the expression is not valid.
2259 * When this function returns true, `checkValue()` should also return true.
2261 bool Expression::checkType()
2266 /****************************************
2267 * Check that the expression has a valid value.
2268 * If not, generates an error "... has no value".
2270 * true if the expression is not valid or has void type.
2272 bool Expression::checkValue()
2274 if (type
&& type
->toBasetype()->ty
== Tvoid
)
2276 error("expression %s is void and has no value", toChars());
2279 type
= Type::terror
;
2285 bool Expression::checkScalar()
2289 if (type
->toBasetype()->ty
== Terror
)
2291 if (!type
->isscalar())
2293 error("'%s' is not a scalar, it is a %s", toChars(), type
->toChars());
2296 return checkValue();
2299 bool Expression::checkNoBool()
2303 if (type
->toBasetype()->ty
== Terror
)
2305 if (type
->toBasetype()->ty
== Tbool
)
2307 error("operation not allowed on bool '%s'", toChars());
2313 bool Expression::checkIntegral()
2317 if (type
->toBasetype()->ty
== Terror
)
2319 if (!type
->isintegral())
2321 error("'%s' is not of integral type, it is a %s", toChars(), type
->toChars());
2324 return checkValue();
2327 bool Expression::checkArithmetic()
2331 if (type
->toBasetype()->ty
== Terror
)
2333 if (!type
->isintegral() && !type
->isfloating())
2335 error("'%s' is not of arithmetic type, it is a %s", toChars(), type
->toChars());
2338 return checkValue();
2341 void Expression::checkDeprecated(Scope
*sc
, Dsymbol
*s
)
2343 s
->checkDeprecated(loc
, sc
);
2346 /*********************************************
2347 * Calling function f.
2348 * Check the purity, i.e. if we're in a pure function
2349 * we can only call other pure functions.
2350 * Returns true if error occurs.
2352 bool Expression::checkPurity(Scope
*sc
, FuncDeclaration
*f
)
2358 if (sc
->intypeof
== 1)
2360 if (sc
->flags
& (SCOPEctfe
| SCOPEdebug
))
2366 * /+pure+/ void h() {
2367 * /+pure+/ void i() { }
2371 * g() can call h() but not f()
2372 * i() can call h() and g() but not f()
2375 // Find the closest pure parent of the calling function
2376 FuncDeclaration
*outerfunc
= sc
->func
;
2377 FuncDeclaration
*calledparent
= f
;
2379 if (outerfunc
->isInstantiated())
2381 // The attributes of outerfunc should be inferred from the call of f.
2383 else if (f
->isInstantiated())
2385 // The attributes of f are inferred from its body.
2387 else if (f
->isFuncLiteralDeclaration())
2389 // The attributes of f are always inferred in its declared place.
2393 /* Today, static local functions are impure by default, but they cannot
2394 * violate purity of enclosing functions.
2396 * auto foo() pure { // non instantiated funciton
2397 * static auto bar() { // static, without pure attribute
2398 * impureFunc(); // impure call
2399 * // Although impureFunc is called inside bar, f(= impureFunc)
2400 * // is not callable inside pure outerfunc(= foo <- bar).
2404 * // Although bar is called inside foo, f(= bar) is callable
2405 * // bacause calledparent(= foo) is same with outerfunc(= foo).
2409 while (outerfunc
->toParent2() &&
2410 outerfunc
->isPureBypassingInference() == PUREimpure
&&
2411 outerfunc
->toParent2()->isFuncDeclaration())
2413 outerfunc
= outerfunc
->toParent2()->isFuncDeclaration();
2414 if (outerfunc
->type
->ty
== Terror
)
2417 while (calledparent
->toParent2() &&
2418 calledparent
->isPureBypassingInference() == PUREimpure
&&
2419 calledparent
->toParent2()->isFuncDeclaration())
2421 calledparent
= calledparent
->toParent2()->isFuncDeclaration();
2422 if (calledparent
->type
->ty
== Terror
)
2427 // If the caller has a pure parent, then either the called func must be pure,
2428 // OR, they must have the same pure parent.
2429 if (!f
->isPure() && calledparent
!= outerfunc
)
2431 FuncDeclaration
*ff
= outerfunc
;
2432 if (sc
->flags
& SCOPEcompile
? ff
->isPureBypassingInference() >= PUREweak
: ff
->setImpure())
2434 error("pure %s '%s' cannot call impure %s '%s'",
2435 ff
->kind(), ff
->toPrettyChars(), f
->kind(), f
->toPrettyChars());
2442 /*******************************************
2443 * Accessing variable v.
2444 * Check for purity and safety violations.
2445 * Returns true if error occurs.
2447 bool Expression::checkPurity(Scope
*sc
, VarDeclaration
*v
)
2449 //printf("v = %s %s\n", v->type->toChars(), v->toChars());
2451 /* Look for purity and safety violations when accessing variable v
2452 * from current function.
2456 if (sc
->intypeof
== 1)
2457 return false; // allow violations inside typeof(expression)
2458 if (sc
->flags
& (SCOPEctfe
| SCOPEdebug
))
2459 return false; // allow violations inside compile-time evaluated expressions and debug conditionals
2460 if (v
->ident
== Id::ctfe
)
2461 return false; // magic variable never violates pure and safe
2462 if (v
->isImmutable())
2463 return false; // always safe and pure to access immutables...
2464 if (v
->isConst() && !v
->isRef() && (v
->isDataseg() || v
->isParameter()) &&
2465 v
->type
->implicitConvTo(v
->type
->immutableOf()))
2466 return false; // or const global/parameter values which have no mutable indirections
2467 if (v
->storage_class
& STCmanifest
)
2468 return false; // ...or manifest constants
2473 // Bugzilla 7533: Accessing implicit generated __gate is pure.
2474 if (v
->ident
== Id::gate
)
2477 /* Accessing global mutable state.
2478 * Therefore, this function and all its immediately enclosing
2479 * functions must be pure.
2481 /* Today, static local functions are impure by default, but they cannot
2482 * violate purity of enclosing functions.
2484 * auto foo() pure { // non instantiated funciton
2485 * static auto bar() { // static, without pure attribute
2486 * globalData++; // impure access
2487 * // Although globalData is accessed inside bar,
2488 * // it is not accessible inside pure foo.
2492 for (Dsymbol
*s
= sc
->func
; s
; s
= s
->toParent2())
2494 FuncDeclaration
*ff
= s
->isFuncDeclaration();
2497 if (sc
->flags
& SCOPEcompile
? ff
->isPureBypassingInference() >= PUREweak
: ff
->setImpure())
2499 error("pure %s '%s' cannot access mutable static data '%s'",
2500 ff
->kind(), ff
->toPrettyChars(), v
->toChars());
2504 /* If the enclosing is an instantiated function or a lambda, its
2505 * attribute inference result is preferred.
2507 if (ff
->isInstantiated())
2509 if (ff
->isFuncLiteralDeclaration())
2520 * /+pure+/ void h() {
2522 * /+pure+/ void i() { }
2526 * i() can modify hx and gx but not fx
2529 Dsymbol
*vparent
= v
->toParent2();
2530 for (Dsymbol
*s
= sc
->func
; !err
&& s
; s
= s
->toParent2())
2535 if (AggregateDeclaration
*ad
= s
->isAggregateDeclaration())
2541 FuncDeclaration
*ff
= s
->isFuncDeclaration();
2544 if (ff
->isNested() || ff
->isThis())
2546 if (ff
->type
->isImmutable() ||
2547 (ff
->type
->isShared() && !MODimplicitConv(ff
->type
->mod
, v
->type
->mod
)))
2551 MODMatchToBuffer(&ffbuf
, ff
->type
->mod
, v
->type
->mod
);
2552 MODMatchToBuffer(&vbuf
, v
->type
->mod
, ff
->type
->mod
);
2553 error("%s%s '%s' cannot access %sdata '%s'",
2554 ffbuf
.peekString(), ff
->kind(), ff
->toPrettyChars(), vbuf
.peekString(), v
->toChars());
2564 /* Do not allow safe functions to access __gshared data
2566 if (v
->storage_class
& STCgshared
)
2568 if (sc
->func
->setUnsafe())
2570 error("safe %s '%s' cannot access __gshared data '%s'",
2571 sc
->func
->kind(), sc
->func
->toChars(), v
->toChars());
2579 /*********************************************
2580 * Calling function f.
2581 * Check the safety, i.e. if we're in a @safe function
2582 * we can only call @safe or @trusted functions.
2583 * Returns true if error occurs.
2585 bool Expression::checkSafety(Scope
*sc
, FuncDeclaration
*f
)
2591 if (sc
->intypeof
== 1)
2593 if (sc
->flags
& SCOPEctfe
)
2596 if (!f
->isSafe() && !f
->isTrusted())
2598 if (sc
->flags
& SCOPEcompile
? sc
->func
->isSafeBypassingInference() : sc
->func
->setUnsafe())
2600 if (loc
.linnum
== 0) // e.g. implicitly generated dtor
2601 loc
= sc
->func
->loc
;
2603 error("@safe %s '%s' cannot call @system %s '%s'",
2604 sc
->func
->kind(), sc
->func
->toPrettyChars(), f
->kind(), f
->toPrettyChars());
2611 /*********************************************
2612 * Calling function f.
2613 * Check the @nogc-ness, i.e. if we're in a @nogc function
2614 * we can only call other @nogc functions.
2615 * Returns true if error occurs.
2617 bool Expression::checkNogc(Scope
*sc
, FuncDeclaration
*f
)
2623 if (sc
->intypeof
== 1)
2625 if (sc
->flags
& SCOPEctfe
)
2630 if (sc
->flags
& SCOPEcompile
? sc
->func
->isNogcBypassingInference() : sc
->func
->setGC())
2632 if (loc
.linnum
== 0) // e.g. implicitly generated dtor
2633 loc
= sc
->func
->loc
;
2635 error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
2636 sc
->func
->kind(), sc
->func
->toPrettyChars(), f
->kind(), f
->toPrettyChars());
2643 /********************************************
2644 * Check that the postblit is callable if t is an array of structs.
2645 * Returns true if error happens.
2647 bool Expression::checkPostblit(Scope
*sc
, Type
*t
)
2649 t
= t
->baseElemOf();
2650 if (t
->ty
== Tstruct
)
2652 // Bugzilla 11395: Require TypeInfo generation for array concatenation
2653 semanticTypeInfo(sc
, t
);
2655 StructDeclaration
*sd
= ((TypeStruct
*)t
)->sym
;
2658 if (sd
->postblit
->storage_class
& STCdisable
)
2660 sd
->error(loc
, "is not copyable because it is annotated with @disable");
2663 //checkDeprecated(sc, sd->postblit); // necessary?
2664 checkPurity(sc
, sd
->postblit
);
2665 checkSafety(sc
, sd
->postblit
);
2666 checkNogc(sc
, sd
->postblit
);
2667 //checkAccess(sd, loc, sc, sd->postblit); // necessary?
2674 bool Expression::checkRightThis(Scope
*sc
)
2678 if (op
== TOKvar
&& type
->ty
!= Terror
)
2680 VarExp
*ve
= (VarExp
*)this;
2681 if (isNeedThisScope(sc
, ve
->var
))
2683 //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
2684 // sc->intypeof, sc->getStructClassScope(), func, fdthis);
2685 error("need 'this' for '%s' of type '%s'", ve
->var
->toChars(), ve
->var
->type
->toChars());
2692 /*******************************
2693 * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
2694 * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
2695 * Returns true if error occurs.
2697 bool Expression::checkReadModifyWrite(TOK rmwOp
, Expression
*ex
)
2699 //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex->toChars() : "");
2700 if (!type
|| !type
->isShared())
2703 // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
2707 case TOKpreplusplus
:
2712 case TOKpreminusminus
:
2720 deprecation("read-modify-write operations are not allowed for shared variables. "
2721 "Use core.atomic.atomicOp!\"%s\"(%s, %s) instead.",
2722 Token::tochars
[rmwOp
], toChars(), ex
? ex
->toChars() : "1");
2725 // note: enable when deprecation becomes an error.
2729 /*****************************
2730 * If expression can be tested for true or false,
2731 * returns the modified expression.
2732 * Otherwise returns ErrorExp.
2734 Expression
*Expression::toBoolean(Scope
*sc
)
2736 // Default is 'yes' - do nothing
2737 Expression
*e
= this;
2739 Type
*tb
= type
->toBasetype();
2742 // Structs can be converted to bool using opCast(bool)()
2743 if (tb
->ty
== Tstruct
)
2745 AggregateDeclaration
*ad
= ((TypeStruct
*)tb
)->sym
;
2746 /* Don't really need to check for opCast first, but by doing so we
2747 * get better error messages if it isn't there.
2749 Dsymbol
*fd
= search_function(ad
, Id::_cast
);
2752 e
= new CastExp(loc
, e
, Type::tbool
);
2753 e
= semantic(e
, sc
);
2757 // Forward to aliasthis.
2758 if (ad
->aliasthis
&& tb
!= att
)
2760 if (!att
&& tb
->checkAliasThisRec())
2762 e
= resolveAliasThis(sc
, e
);
2764 tb
= e
->type
->toBasetype();
2769 if (!t
->isBoolean())
2771 if (tb
!= Type::terror
)
2772 error("expression %s of type %s does not have a boolean value", toChars(), t
->toChars());
2773 return new ErrorExp();
2778 /******************************
2779 * Take address of expression.
2782 Expression
*Expression::addressOf()
2784 //printf("Expression::addressOf()\n");
2785 Expression
*e
= new AddrExp(loc
, this);
2786 e
->type
= type
->pointerTo();
2790 /******************************
2791 * If this is a reference, dereference it.
2794 Expression
*Expression::deref()
2796 //printf("Expression::deref()\n");
2797 // type could be null if forward referencing an 'auto' variable
2798 if (type
&& type
->ty
== Treference
)
2800 Expression
*e
= new PtrExp(loc
, this);
2801 e
->type
= ((TypeReference
*)type
)->next
;
2807 /********************************
2808 * Does this expression statically evaluate to a boolean 'result' (true or false)?
2810 bool Expression::isBool(bool)
2815 /****************************************
2816 * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc.
2819 Expression
*Expression::resolveLoc(Loc
, Scope
*)
2824 Expressions
*Expression::arraySyntaxCopy(Expressions
*exps
)
2826 Expressions
*a
= NULL
;
2829 a
= new Expressions();
2830 a
->setDim(exps
->dim
);
2831 for (size_t i
= 0; i
< a
->dim
; i
++)
2833 Expression
*e
= (*exps
)[i
];
2834 (*a
)[i
] = e
? e
->syntaxCopy() : NULL
;
2840 /************************************************
2841 * Destructors are attached to VarDeclarations.
2842 * Hence, if expression returns a temp that needs a destructor,
2843 * make sure and create a VarDeclaration for that temp.
2846 Expression
*Expression::addDtorHook(Scope
*)
2851 /******************************** IntegerExp **************************/
2853 IntegerExp::IntegerExp(Loc loc
, dinteger_t value
, Type
*type
)
2854 : Expression(loc
, TOKint64
, sizeof(IntegerExp
))
2856 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
2858 if (!type
->isscalar())
2860 //printf("%s, loc = %d\n", toChars(), loc.linnum);
2861 if (type
->ty
!= Terror
)
2862 error("integral constant must be scalar type, not %s", type
->toChars());
2863 type
= Type::terror
;
2869 IntegerExp::IntegerExp(dinteger_t value
)
2870 : Expression(Loc(), TOKint64
, sizeof(IntegerExp
))
2872 this->type
= Type::tint32
;
2873 this->value
= (d_int32
) value
;
2876 IntegerExp
*IntegerExp::create(Loc loc
, dinteger_t value
, Type
*type
)
2878 return new IntegerExp(loc
, value
, type
);
2881 bool IntegerExp::equals(RootObject
*o
)
2885 if (((Expression
*)o
)->op
== TOKint64
)
2887 IntegerExp
*ne
= (IntegerExp
*)o
;
2888 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
2897 void IntegerExp::setInteger(dinteger_t value
)
2899 this->value
= value
;
2903 void IntegerExp::normalize()
2905 /* 'Normalize' the value of the integer to be in range of the type
2907 switch (type
->toBasetype()->ty
)
2909 case Tbool
: value
= (value
!= 0); break;
2910 case Tint8
: value
= (d_int8
) value
; break;
2912 case Tuns8
: value
= (d_uns8
) value
; break;
2913 case Tint16
: value
= (d_int16
) value
; break;
2915 case Tuns16
: value
= (d_uns16
) value
; break;
2916 case Tint32
: value
= (d_int32
) value
; break;
2918 case Tuns32
: value
= (d_uns32
) value
; break;
2919 case Tint64
: value
= (d_int64
) value
; break;
2920 case Tuns64
: value
= (d_uns64
) value
; break;
2922 if (Target::ptrsize
== 4)
2923 value
= (d_uns32
) value
;
2924 else if (Target::ptrsize
== 8)
2925 value
= (d_uns64
) value
;
2934 dinteger_t
IntegerExp::toInteger()
2936 normalize(); // necessary until we fix all the paints of 'type'
2940 real_t
IntegerExp::toReal()
2942 normalize(); // necessary until we fix all the paints of 'type'
2943 Type
*t
= type
->toBasetype();
2944 if (t
->ty
== Tuns64
)
2945 return ldouble((d_uns64
)value
);
2947 return ldouble((d_int64
)value
);
2950 real_t
IntegerExp::toImaginary()
2952 return CTFloat::zero
;
2955 complex_t
IntegerExp::toComplex()
2957 return (complex_t
)toReal();
2960 bool IntegerExp::isBool(bool result
)
2962 bool r
= toInteger() != 0;
2963 return result
? r
: !r
;
2966 Expression
*IntegerExp::toLvalue(Scope
*, Expression
*e
)
2970 else if (!loc
.filename
)
2972 e
->error("constant %s is not an lvalue", e
->toChars());
2973 return new ErrorExp();
2976 /******************************** ErrorExp **************************/
2978 /* Use this expression for error recovery.
2979 * It should behave as a 'sink' to prevent further cascaded error messages.
2982 ErrorExp::ErrorExp()
2983 : Expression(Loc(), TOKerror
, sizeof(ErrorExp
))
2985 type
= Type::terror
;
2988 Expression
*ErrorExp::toLvalue(Scope
*, Expression
*)
2993 /******************************** RealExp **************************/
2995 RealExp::RealExp(Loc loc
, real_t value
, Type
*type
)
2996 : Expression(loc
, TOKfloat64
, sizeof(RealExp
))
2998 //printf("RealExp::RealExp(%Lg)\n", value);
2999 this->value
= value
;
3003 RealExp
*RealExp::create(Loc loc
, real_t value
, Type
*type
)
3005 return new RealExp(loc
, value
,type
);
3008 dinteger_t
RealExp::toInteger()
3010 return (sinteger_t
) toReal();
3013 uinteger_t
RealExp::toUInteger()
3015 return (uinteger_t
) toReal();
3018 real_t
RealExp::toReal()
3020 return type
->isreal() ? value
: CTFloat::zero
;
3023 real_t
RealExp::toImaginary()
3025 return type
->isreal() ? CTFloat::zero
: value
;
3028 complex_t
RealExp::toComplex()
3030 return complex_t(toReal(), toImaginary());
3033 /********************************
3034 * Test to see if two reals are the same.
3035 * Regard NaN's as equivalent.
3036 * Regard +0 and -0 as different.
3039 int RealEquals(real_t x1
, real_t x2
)
3041 return (CTFloat::isNaN(x1
) && CTFloat::isNaN(x2
)) ||
3042 CTFloat::isIdentical(x1
, x2
);
3045 bool RealExp::equals(RootObject
*o
)
3049 if (((Expression
*)o
)->op
== TOKfloat64
)
3051 RealExp
*ne
= (RealExp
*)o
;
3052 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
3053 RealEquals(value
, ne
->value
))
3061 bool RealExp::isBool(bool result
)
3063 return result
? (bool)value
: !(bool)value
;
3066 /******************************** ComplexExp **************************/
3068 ComplexExp::ComplexExp(Loc loc
, complex_t value
, Type
*type
)
3069 : Expression(loc
, TOKcomplex80
, sizeof(ComplexExp
)), value(value
)
3072 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
3075 ComplexExp
*ComplexExp::create(Loc loc
, complex_t value
, Type
*type
)
3077 return new ComplexExp(loc
, value
, type
);
3080 dinteger_t
ComplexExp::toInteger()
3082 return (sinteger_t
) toReal();
3085 uinteger_t
ComplexExp::toUInteger()
3087 return (uinteger_t
) toReal();
3090 real_t
ComplexExp::toReal()
3092 return creall(value
);
3095 real_t
ComplexExp::toImaginary()
3097 return cimagl(value
);
3100 complex_t
ComplexExp::toComplex()
3105 bool ComplexExp::equals(RootObject
*o
)
3109 if (((Expression
*)o
)->op
== TOKcomplex80
)
3111 ComplexExp
*ne
= (ComplexExp
*)o
;
3112 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
3113 RealEquals(creall(value
), creall(ne
->value
)) &&
3114 RealEquals(cimagl(value
), cimagl(ne
->value
)))
3122 bool ComplexExp::isBool(bool result
)
3125 return (bool)(value
);
3130 /******************************** IdentifierExp **************************/
3132 IdentifierExp::IdentifierExp(Loc loc
, Identifier
*ident
)
3133 : Expression(loc
, TOKidentifier
, sizeof(IdentifierExp
))
3135 this->ident
= ident
;
3138 IdentifierExp
*IdentifierExp::create(Loc loc
, Identifier
*ident
)
3140 return new IdentifierExp(loc
, ident
);
3143 bool IdentifierExp::isLvalue()
3148 Expression
*IdentifierExp::toLvalue(Scope
*, Expression
*)
3153 /******************************** DollarExp **************************/
3155 DollarExp::DollarExp(Loc loc
)
3156 : IdentifierExp(loc
, Id::dollar
)
3160 /******************************** DsymbolExp **************************/
3162 DsymbolExp::DsymbolExp(Loc loc
, Dsymbol
*s
, bool hasOverloads
)
3163 : Expression(loc
, TOKdsymbol
, sizeof(DsymbolExp
))
3166 this->hasOverloads
= hasOverloads
;
3169 /****************************************
3170 * Resolve a symbol `s` and wraps it in an expression object.
3172 * hasOverloads = works if the aliased symbol is a function.
3173 * true: it's overloaded and will be resolved later.
3174 * false: it's exact function symbol.
3176 Expression
*resolve(Loc loc
, Scope
*sc
, Dsymbol
*s
, bool hasOverloads
)
3181 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
3182 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
3184 Declaration
*d
= s
->isDeclaration();
3185 if (d
&& (d
->storage_class
& STCtemplateparameter
))
3191 if (!s
->isFuncDeclaration()) // functions are checked after overloading
3192 s
->checkDeprecated(loc
, sc
);
3194 // Bugzilla 12023: if 's' is a tuple variable, the tuple is returned.
3197 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
3198 if (s
!= olds
&& !s
->isFuncDeclaration())
3199 s
->checkDeprecated(loc
, sc
);
3202 if (EnumMember
*em
= s
->isEnumMember())
3204 return em
->getVarExp(loc
, sc
);
3206 if (VarDeclaration
*v
= s
->isVarDeclaration())
3208 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
3209 if (!v
->type
|| // during variable type inference
3210 (!v
->type
->deco
&& v
->inuse
)) // during variable type semantic
3212 if (v
->inuse
) // variable type depends on the variable itself
3213 ::error(loc
, "circular reference to %s '%s'", v
->kind(), v
->toPrettyChars());
3214 else // variable type cannot be determined
3215 ::error(loc
, "forward reference to %s '%s'", v
->kind(), v
->toPrettyChars());
3216 return new ErrorExp();
3218 if (v
->type
->ty
== Terror
)
3219 return new ErrorExp();
3221 if ((v
->storage_class
& STCmanifest
) && v
->_init
)
3225 ::error(loc
, "circular initialization of %s '%s'", v
->kind(), v
->toPrettyChars());
3226 return new ErrorExp();
3229 e
= v
->expandInitializer(loc
);
3231 e
= semantic(e
, sc
);
3236 // Change the ancestor lambdas to delegate before hasThis(sc) call.
3237 if (v
->checkNestedReference(sc
, loc
))
3238 return new ErrorExp();
3240 if (v
->needThis() && hasThis(sc
))
3241 e
= new DotVarExp(loc
, new ThisExp(loc
), v
);
3243 e
= new VarExp(loc
, v
);
3244 e
= semantic(e
, sc
);
3247 if (FuncLiteralDeclaration
*fld
= s
->isFuncLiteralDeclaration())
3249 //printf("'%s' is a function literal\n", fld->toChars());
3250 e
= new FuncExp(loc
, fld
);
3251 return semantic(e
, sc
);
3253 if (FuncDeclaration
*f
= s
->isFuncDeclaration())
3255 f
= f
->toAliasFunc();
3256 if (!f
->functionSemantic())
3257 return new ErrorExp();
3259 if (!hasOverloads
&& f
->checkForwardRef(loc
))
3260 return new ErrorExp();
3262 FuncDeclaration
*fd
= s
->isFuncDeclaration();
3264 return new VarExp(loc
, fd
, hasOverloads
);
3266 if (OverDeclaration
*od
= s
->isOverDeclaration())
3268 e
= new VarExp(loc
, od
, true);
3269 e
->type
= Type::tvoid
;
3272 if (OverloadSet
*o
= s
->isOverloadSet())
3274 //printf("'%s' is an overload set\n", o->toChars());
3275 return new OverExp(loc
, o
);
3278 if (Import
*imp
= s
->isImport())
3282 ::error(loc
, "forward reference of import %s", imp
->toChars());
3283 return new ErrorExp();
3285 ScopeExp
*ie
= new ScopeExp(loc
, imp
->pkg
);
3286 return semantic(ie
, sc
);
3288 if (Package
*pkg
= s
->isPackage())
3290 ScopeExp
*ie
= new ScopeExp(loc
, pkg
);
3291 return semantic(ie
, sc
);
3293 if (Module
*mod
= s
->isModule())
3295 ScopeExp
*ie
= new ScopeExp(loc
, mod
);
3296 return semantic(ie
, sc
);
3299 if (Nspace
*ns
= s
->isNspace())
3301 ScopeExp
*ie
= new ScopeExp(loc
, ns
);
3302 return semantic(ie
, sc
);
3305 if (Type
*t
= s
->getType())
3307 return semantic(new TypeExp(loc
, t
), sc
);
3310 if (TupleDeclaration
*tup
= s
->isTupleDeclaration())
3312 if (tup
->needThis() && hasThis(sc
))
3313 e
= new DotVarExp(loc
, new ThisExp(loc
), tup
);
3315 e
= new TupleExp(loc
, tup
);
3316 e
= semantic(e
, sc
);
3320 if (TemplateInstance
*ti
= s
->isTemplateInstance())
3323 if (!ti
->inst
|| ti
->errors
)
3324 return new ErrorExp();
3326 if (!s
->isTemplateInstance())
3328 e
= new ScopeExp(loc
, ti
);
3329 e
= semantic(e
, sc
);
3332 if (TemplateDeclaration
*td
= s
->isTemplateDeclaration())
3334 Dsymbol
*p
= td
->toParent2();
3335 FuncDeclaration
*fdthis
= hasThis(sc
);
3336 AggregateDeclaration
*ad
= p
? p
->isAggregateDeclaration() : NULL
;
3337 if (fdthis
&& ad
&& isAggregate(fdthis
->vthis
->type
) == ad
&&
3338 (td
->_scope
->stc
& STCstatic
) == 0)
3340 e
= new DotTemplateExp(loc
, new ThisExp(loc
), td
);
3343 e
= new TemplateExp(loc
, td
);
3344 e
= semantic(e
, sc
);
3348 ::error(loc
, "%s '%s' is not a variable", s
->kind(), s
->toChars());
3349 return new ErrorExp();
3352 bool DsymbolExp::isLvalue()
3357 Expression
*DsymbolExp::toLvalue(Scope
*, Expression
*)
3362 /******************************** ThisExp **************************/
3364 ThisExp::ThisExp(Loc loc
)
3365 : Expression(loc
, TOKthis
, sizeof(ThisExp
))
3367 //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
3371 bool ThisExp::isBool(bool result
)
3373 return result
? true : false;
3376 bool ThisExp::isLvalue()
3378 // Class `this` should be an rvalue; struct `this` should be an lvalue.
3379 return type
->toBasetype()->ty
!= Tclass
;
3382 Expression
*ThisExp::toLvalue(Scope
*sc
, Expression
*e
)
3384 if (type
->toBasetype()->ty
== Tclass
)
3386 // Class `this` is an rvalue; struct `this` is an lvalue.
3387 return Expression::toLvalue(sc
, e
);
3392 /******************************** SuperExp **************************/
3394 SuperExp::SuperExp(Loc loc
)
3400 /******************************** NullExp **************************/
3402 NullExp::NullExp(Loc loc
, Type
*type
)
3403 : Expression(loc
, TOKnull
, sizeof(NullExp
))
3409 bool NullExp::equals(RootObject
*o
)
3411 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
)
3413 Expression
*e
= (Expression
*)o
;
3414 if (e
->op
== TOKnull
&&
3415 type
->equals(e
->type
))
3423 bool NullExp::isBool(bool result
)
3425 return result
? false : true;
3428 StringExp
*NullExp::toStringExp()
3430 if (implicitConvTo(Type::tstring
))
3432 StringExp
*se
= new StringExp(loc
, (char*)mem
.xcalloc(1, 1), 0);
3433 se
->type
= Type::tstring
;
3439 /******************************** StringExp **************************/
3441 StringExp::StringExp(Loc loc
, char *string
)
3442 : Expression(loc
, TOKstring
, sizeof(StringExp
))
3444 this->string
= string
;
3445 this->len
= strlen(string
);
3447 this->committed
= 0;
3449 this->ownedByCtfe
= OWNEDcode
;
3452 StringExp::StringExp(Loc loc
, void *string
, size_t len
)
3453 : Expression(loc
, TOKstring
, sizeof(StringExp
))
3455 this->string
= string
;
3458 this->committed
= 0;
3460 this->ownedByCtfe
= OWNEDcode
;
3463 StringExp::StringExp(Loc loc
, void *string
, size_t len
, utf8_t postfix
)
3464 : Expression(loc
, TOKstring
, sizeof(StringExp
))
3466 this->string
= string
;
3469 this->committed
= 0;
3470 this->postfix
= postfix
;
3471 this->ownedByCtfe
= OWNEDcode
;
3474 StringExp
*StringExp::create(Loc loc
, char *s
)
3476 return new StringExp(loc
, s
);
3479 StringExp
*StringExp::create(Loc loc
, void *string
, size_t len
)
3481 return new StringExp(loc
, string
, len
);
3484 bool StringExp::equals(RootObject
*o
)
3486 //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
3487 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
)
3489 Expression
*e
= (Expression
*)o
;
3490 if (e
->op
== TOKstring
)
3492 return compare(o
) == 0;
3498 /**********************************
3499 * Return the number of code units the string would be if it were re-encoded
3502 * tynto = code unit type of the target encoding
3504 * number of code units
3507 size_t StringExp::numberOfCodeUnits(int tynto
) const
3513 case Tchar
: encSize
= 1; break;
3514 case Twchar
: encSize
= 2; break;
3515 case Tdchar
: encSize
= 4; break;
3528 for (size_t u
= 0; u
< len
;)
3530 if (const char *p
= utf_decodeChar((utf8_t
*)string
, len
, &u
, &c
))
3535 result
+= utf_codeLength(encSize
, c
);
3540 for (size_t u
= 0; u
< len
;)
3542 if (const char *p
= utf_decodeWchar((utf16_t
*)string
, len
, &u
, &c
))
3547 result
+= utf_codeLength(encSize
, c
);
3552 for (size_t u
= 0; u
< len
;)
3554 c
= *((utf32_t
*)((char *)string
+ u
));
3556 result
+= utf_codeLength(encSize
, c
);
3566 /**********************************************
3567 * Write the contents of the string to dest.
3568 * Use numberOfCodeUnits() to determine size of result.
3570 * dest = destination
3571 * tyto = encoding type of the result
3572 * zero = add terminating 0
3574 void StringExp::writeTo(void *dest
, bool zero
, int tyto
) const
3579 case 0: encSize
= sz
; break;
3580 case Tchar
: encSize
= 1; break;
3581 case Twchar
: encSize
= 2; break;
3582 case Tdchar
: encSize
= 4; break;
3588 memcpy(dest
, string
, len
* sz
);
3590 memset((char *)dest
+ len
* sz
, 0, sz
);
3596 /**************************************************
3597 * If the string data is UTF-8 and can be accessed directly,
3598 * return a pointer to it.
3599 * Do not assume a terminating 0.
3601 * pointer to string data if possible, null if not
3603 char *StringExp::toPtr()
3605 return (sz
== 1) ? (char*)string
: NULL
;
3608 StringExp
*StringExp::toStringExp()
3613 /****************************************
3614 * Convert string to char[].
3617 StringExp
*StringExp::toUTF8(Scope
*sc
)
3620 { // Convert to UTF-8 string
3622 Expression
*e
= castTo(sc
, Type::tchar
->arrayOf());
3623 e
= e
->optimize(WANTvalue
);
3624 assert(e
->op
== TOKstring
);
3625 StringExp
*se
= (StringExp
*)e
;
3626 assert(se
->sz
== 1);
3632 int StringExp::compare(RootObject
*obj
)
3634 //printf("StringExp::compare()\n");
3635 // Used to sort case statement expressions so we can do an efficient lookup
3636 StringExp
*se2
= (StringExp
*)(obj
);
3638 // This is a kludge so isExpression() in template.c will return 5
3643 assert(se2
->op
== TOKstring
);
3646 size_t len2
= se2
->len
;
3648 //printf("sz = %d, len1 = %d, len2 = %d\n", sz, (int)len1, (int)len2);
3654 return memcmp((char *)string
, (char *)se2
->string
, len1
);
3658 d_uns16
*s1
= (d_uns16
*)string
;
3659 d_uns16
*s2
= (d_uns16
*)se2
->string
;
3661 for (size_t u
= 0; u
< len
; u
++)
3664 return s1
[u
] - s2
[u
];
3671 d_uns32
*s1
= (d_uns32
*)string
;
3672 d_uns32
*s2
= (d_uns32
*)se2
->string
;
3674 for (size_t u
= 0; u
< len
; u
++)
3677 return s1
[u
] - s2
[u
];
3686 return (int)(len1
- len2
);
3689 bool StringExp::isBool(bool result
)
3691 return result
? true : false;
3695 bool StringExp::isLvalue()
3697 /* string literal is rvalue in default, but
3698 * conversion to reference of static array is only allowed.
3700 return (type
&& type
->toBasetype()->ty
== Tsarray
);
3703 Expression
*StringExp::toLvalue(Scope
*sc
, Expression
*e
)
3705 //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
3706 return (type
&& type
->toBasetype()->ty
== Tsarray
)
3707 ? this : Expression::toLvalue(sc
, e
);
3710 Expression
*StringExp::modifiableLvalue(Scope
*, Expression
*)
3712 error("cannot modify string literal %s", toChars());
3713 return new ErrorExp();
3716 unsigned StringExp::charAt(uinteger_t i
) const
3722 value
= ((utf8_t
*)string
)[(size_t)i
];
3726 value
= ((unsigned short *)string
)[(size_t)i
];
3730 value
= ((unsigned int *)string
)[(size_t)i
];
3740 /************************ ArrayLiteralExp ************************************/
3742 // [ e1, e2, e3, ... ]
3744 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expressions
*elements
)
3745 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
3748 this->elements
= elements
;
3749 this->ownedByCtfe
= OWNEDcode
;
3752 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expression
*e
)
3753 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
3756 elements
= new Expressions
;
3758 this->ownedByCtfe
= OWNEDcode
;
3761 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expression
*basis
, Expressions
*elements
)
3762 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
3764 this->basis
= basis
;
3765 this->elements
= elements
;
3766 this->ownedByCtfe
= OWNEDcode
;
3769 ArrayLiteralExp
*ArrayLiteralExp::create(Loc loc
, Expressions
*elements
)
3771 return new ArrayLiteralExp(loc
, elements
);
3774 bool ArrayLiteralExp::equals(RootObject
*o
)
3778 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
&&
3779 ((Expression
*)o
)->op
== TOKarrayliteral
)
3781 ArrayLiteralExp
*ae
= (ArrayLiteralExp
*)o
;
3782 if (elements
->dim
!= ae
->elements
->dim
)
3784 if (elements
->dim
== 0 &&
3785 !type
->equals(ae
->type
))
3789 for (size_t i
= 0; i
< elements
->dim
; i
++)
3791 Expression
*e1
= (*elements
)[i
];
3792 Expression
*e2
= (*ae
->elements
)[i
];
3798 (!e1
|| !e2
|| !e1
->equals(e2
)))
3806 Expression
*ArrayLiteralExp::syntaxCopy()
3808 return new ArrayLiteralExp(loc
,
3809 basis
? basis
->syntaxCopy() : NULL
,
3810 arraySyntaxCopy(elements
));
3813 Expression
*ArrayLiteralExp::getElement(d_size_t i
)
3815 Expression
*el
= (*elements
)[i
];
3821 static void appendArrayLiteral(Expressions
*elems
, ArrayLiteralExp
*ale
)
3825 size_t d
= elems
->dim
;
3826 elems
->append(ale
->elements
);
3827 for (size_t i
= d
; i
< elems
->dim
; i
++)
3829 Expression
*el
= (*elems
)[i
];
3831 (*elems
)[i
] = ale
->basis
;
3835 /* Copy element `Expressions` in the parameters when they're `ArrayLiteralExp`s.
3837 * e1 = If it's ArrayLiteralExp, its `elements` will be copied.
3838 * Otherwise, `e1` itself will be pushed into the new `Expressions`.
3839 * e2 = If it's not `null`, it will be pushed/appended to the new
3840 * `Expressions` by the same way with `e1`.
3842 * Newly allocated `Expressions`. Note that it points to the original
3843 * `Expression` values in e1 and e2.
3845 Expressions
* ArrayLiteralExp::copyElements(Expression
*e1
, Expression
*e2
)
3847 Expressions
*elems
= new Expressions();
3849 if (e1
->op
== TOKarrayliteral
)
3850 appendArrayLiteral(elems
, (ArrayLiteralExp
*)e1
);
3856 if (e2
->op
== TOKarrayliteral
)
3857 appendArrayLiteral(elems
, (ArrayLiteralExp
*)e2
);
3865 bool ArrayLiteralExp::isBool(bool result
)
3867 size_t dim
= elements
? elements
->dim
: 0;
3868 return result
? (dim
!= 0) : (dim
== 0);
3871 StringExp
*ArrayLiteralExp::toStringExp()
3873 TY telem
= type
->nextOf()->toBasetype()->ty
;
3875 if (telem
== Tchar
|| telem
== Twchar
|| telem
== Tdchar
||
3876 (telem
== Tvoid
&& (!elements
|| elements
->dim
== 0)))
3878 unsigned char sz
= 1;
3879 if (telem
== Twchar
) sz
= 2;
3880 else if (telem
== Tdchar
) sz
= 4;
3885 for (size_t i
= 0; i
< elements
->dim
; ++i
)
3887 Expression
*ch
= getElement(i
);
3888 if (ch
->op
!= TOKint64
)
3891 buf
.writeByte((unsigned)ch
->toInteger());
3893 buf
.writeword((unsigned)ch
->toInteger());
3895 buf
.write4((unsigned)ch
->toInteger());
3899 if (sz
== 1) { prefix
= 'c'; buf
.writeByte(0); }
3900 else if (sz
== 2) { prefix
= 'w'; buf
.writeword(0); }
3901 else { prefix
= 'd'; buf
.write4(0); }
3903 const size_t len
= buf
.offset
/ sz
- 1;
3904 StringExp
*se
= new StringExp(loc
, buf
.extractData(), len
, prefix
);
3912 /************************ AssocArrayLiteralExp ************************************/
3914 // [ key0 : value0, key1 : value1, ... ]
3916 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc
,
3917 Expressions
*keys
, Expressions
*values
)
3918 : Expression(loc
, TOKassocarrayliteral
, sizeof(AssocArrayLiteralExp
))
3920 assert(keys
->dim
== values
->dim
);
3922 this->values
= values
;
3923 this->ownedByCtfe
= OWNEDcode
;
3926 bool AssocArrayLiteralExp::equals(RootObject
*o
)
3930 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
&&
3931 ((Expression
*)o
)->op
== TOKassocarrayliteral
)
3933 AssocArrayLiteralExp
*ae
= (AssocArrayLiteralExp
*)o
;
3934 if (keys
->dim
!= ae
->keys
->dim
)
3937 for (size_t i
= 0; i
< keys
->dim
; i
++)
3939 for (size_t j
= 0; j
< ae
->keys
->dim
; j
++)
3941 if ((*keys
)[i
]->equals((*ae
->keys
)[j
]))
3943 if (!(*values
)[i
]->equals((*ae
->values
)[j
]))
3949 return count
== keys
->dim
;
3954 Expression
*AssocArrayLiteralExp::syntaxCopy()
3956 return new AssocArrayLiteralExp(loc
,
3957 arraySyntaxCopy(keys
), arraySyntaxCopy(values
));
3960 bool AssocArrayLiteralExp::isBool(bool result
)
3962 size_t dim
= keys
->dim
;
3963 return result
? (dim
!= 0) : (dim
== 0);
3966 /************************ StructLiteralExp ************************************/
3968 // sd( e1, e2, e3, ... )
3970 StructLiteralExp::StructLiteralExp(Loc loc
, StructDeclaration
*sd
, Expressions
*elements
, Type
*stype
)
3971 : Expression(loc
, TOKstructliteral
, sizeof(StructLiteralExp
))
3975 elements
= new Expressions();
3976 this->elements
= elements
;
3977 this->stype
= stype
;
3978 this->useStaticInit
= false;
3980 this->ownedByCtfe
= OWNEDcode
;
3981 this->origin
= this;
3982 this->stageflags
= 0;
3983 this->inlinecopy
= NULL
;
3984 //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars());
3987 StructLiteralExp
*StructLiteralExp::create(Loc loc
, StructDeclaration
*sd
, void *elements
, Type
*stype
)
3989 return new StructLiteralExp(loc
, sd
, (Expressions
*)elements
, stype
);
3992 bool StructLiteralExp::equals(RootObject
*o
)
3996 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
&&
3997 ((Expression
*)o
)->op
== TOKstructliteral
)
3999 StructLiteralExp
*se
= (StructLiteralExp
*)o
;
4000 if (!type
->equals(se
->type
))
4002 if (elements
->dim
!= se
->elements
->dim
)
4004 for (size_t i
= 0; i
< elements
->dim
; i
++)
4006 Expression
*e1
= (*elements
)[i
];
4007 Expression
*e2
= (*se
->elements
)[i
];
4009 (!e1
|| !e2
|| !e1
->equals(e2
)))
4017 Expression
*StructLiteralExp::syntaxCopy()
4019 StructLiteralExp
*exp
= new StructLiteralExp(loc
, sd
, arraySyntaxCopy(elements
), type
? type
: stype
);
4024 Expression
*StructLiteralExp::addDtorHook(Scope
*sc
)
4026 /* If struct requires a destructor, rewrite as:
4028 * so that the destructor can be hung on tmp.
4030 if (sd
->dtor
&& sc
->func
)
4032 /* Make an identifier for the temporary of the form:
4033 * __sl%s%d, where %s is the struct name
4035 const size_t len
= 10;
4038 strcpy(buf
, "__sl");
4039 strncat(buf
, sd
->ident
->toChars(), len
- 4 - 1);
4040 assert(buf
[len
] == 0);
4042 VarDeclaration
*tmp
= copyToTemp(0, buf
, this);
4043 Expression
*ae
= new DeclarationExp(loc
, tmp
);
4044 Expression
*e
= new CommaExp(loc
, ae
, new VarExp(loc
, tmp
));
4045 e
= semantic(e
, sc
);
4051 /**************************************
4052 * Gets expression at offset of type.
4053 * Returns NULL if not found.
4056 Expression
*StructLiteralExp::getField(Type
*type
, unsigned offset
)
4058 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
4059 // /*toChars()*/"", type->toChars(), offset);
4060 Expression
*e
= NULL
;
4061 int i
= getFieldIndex(type
, offset
);
4065 //printf("\ti = %d\n", i);
4066 if (i
== (int)sd
->fields
.dim
- 1 && sd
->isNested())
4069 assert(i
< (int)elements
->dim
);
4073 //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
4075 /* If type is a static array, and e is an initializer for that array,
4076 * then the field initializer should be an array literal of e.
4078 if (e
->type
->castMod(0) != type
->castMod(0) && type
->ty
== Tsarray
)
4079 { TypeSArray
*tsa
= (TypeSArray
*)type
;
4080 size_t length
= (size_t)tsa
->dim
->toInteger();
4081 Expressions
*z
= new Expressions
;
4083 for (size_t q
= 0; q
< length
; ++q
)
4084 (*z
)[q
] = e
->copy();
4085 e
= new ArrayLiteralExp(loc
, z
);
4093 if (useStaticInit
&& e
->op
== TOKstructliteral
&&
4094 e
->type
->needsNested())
4096 StructLiteralExp
*se
= (StructLiteralExp
*)e
;
4097 se
->useStaticInit
= true;
4104 /************************************
4105 * Get index of field.
4106 * Returns -1 if not found.
4109 int StructLiteralExp::getFieldIndex(Type
*type
, unsigned offset
)
4111 /* Find which field offset is by looking at the field offsets
4115 for (size_t i
= 0; i
< sd
->fields
.dim
; i
++)
4117 VarDeclaration
*v
= sd
->fields
[i
];
4119 if (offset
== v
->offset
&&
4120 type
->size() == v
->type
->size())
4122 /* context field might not be filled. */
4123 if (i
== sd
->fields
.dim
- 1 && sd
->isNested())
4125 Expression
*e
= (*elements
)[i
];
4137 /************************ TypeDotIdExp ************************************/
4146 DotIdExp
*typeDotIdExp(Loc loc
, Type
*type
, Identifier
*ident
)
4148 return new DotIdExp(loc
, new TypeExp(loc
, type
), ident
);
4152 /************************************************************/
4154 // Mainly just a placeholder
4156 TypeExp::TypeExp(Loc loc
, Type
*type
)
4157 : Expression(loc
, TOKtype
, sizeof(TypeExp
))
4159 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
4163 Expression
*TypeExp::syntaxCopy()
4165 return new TypeExp(loc
, type
->syntaxCopy());
4168 bool TypeExp::checkType()
4170 error("type %s is not an expression", toChars());
4174 bool TypeExp::checkValue()
4176 error("type %s has no value", toChars());
4180 /************************************************************/
4182 /***********************************************************
4183 * Mainly just a placeholder of
4184 * Package, Module, Nspace, and TemplateInstance (including TemplateMixin)
4186 * A template instance that requires IFTI:
4187 * foo!tiargs(fargs) // foo!tiargs
4188 * is left until CallExp::semantic() or resolveProperties()
4190 ScopeExp::ScopeExp(Loc loc
, ScopeDsymbol
*sds
)
4191 : Expression(loc
, TOKscope
, sizeof(ScopeExp
))
4193 //printf("ScopeExp::ScopeExp(sds = '%s')\n", sds->toChars());
4194 //static int count; if (++count == 38) *(char*)0=0;
4196 assert(!sds
->isTemplateDeclaration()); // instead, you should use TemplateExp
4199 Expression
*ScopeExp::syntaxCopy()
4201 return new ScopeExp(loc
, (ScopeDsymbol
*)sds
->syntaxCopy(NULL
));
4204 bool ScopeExp::checkType()
4206 if (sds
->isPackage())
4208 error("%s %s has no type", sds
->kind(), sds
->toChars());
4211 if (TemplateInstance
*ti
= sds
->isTemplateInstance())
4213 //assert(ti->needsTypeInference(sc));
4215 ti
->semantictiargsdone
&&
4216 ti
->semanticRun
== PASSinit
)
4218 error("partial %s %s has no type", sds
->kind(), toChars());
4225 bool ScopeExp::checkValue()
4227 error("%s %s has no value", sds
->kind(), sds
->toChars());
4231 /********************** TemplateExp **************************************/
4233 // Mainly just a placeholder
4235 TemplateExp::TemplateExp(Loc loc
, TemplateDeclaration
*td
, FuncDeclaration
*fd
)
4236 : Expression(loc
, TOKtemplate
, sizeof(TemplateExp
))
4238 //printf("TemplateExp(): %s\n", td->toChars());
4243 bool TemplateExp::checkType()
4245 error("%s %s has no type", td
->kind(), toChars());
4249 bool TemplateExp::checkValue()
4251 error("%s %s has no value", td
->kind(), toChars());
4255 bool TemplateExp::isLvalue()
4260 Expression
*TemplateExp::toLvalue(Scope
*sc
, Expression
*e
)
4263 return Expression::toLvalue(sc
, e
);
4266 return resolve(loc
, sc
, fd
, true);
4269 /********************** NewExp **************************************/
4271 /* thisexp.new(newargs) newtype(arguments) */
4273 NewExp::NewExp(Loc loc
, Expression
*thisexp
, Expressions
*newargs
,
4274 Type
*newtype
, Expressions
*arguments
)
4275 : Expression(loc
, TOKnew
, sizeof(NewExp
))
4277 this->thisexp
= thisexp
;
4278 this->newargs
= newargs
;
4279 this->newtype
= newtype
;
4280 this->arguments
= arguments
;
4287 NewExp
*NewExp::create(Loc loc
, Expression
*thisexp
, Expressions
*newargs
,
4288 Type
*newtype
, Expressions
*arguments
)
4290 return new NewExp(loc
, thisexp
, newargs
, newtype
, arguments
);
4293 Expression
*NewExp::syntaxCopy()
4295 return new NewExp(loc
,
4296 thisexp
? thisexp
->syntaxCopy() : NULL
,
4297 arraySyntaxCopy(newargs
),
4298 newtype
->syntaxCopy(), arraySyntaxCopy(arguments
));
4301 /********************** NewAnonClassExp **************************************/
4303 NewAnonClassExp::NewAnonClassExp(Loc loc
, Expression
*thisexp
,
4304 Expressions
*newargs
, ClassDeclaration
*cd
, Expressions
*arguments
)
4305 : Expression(loc
, TOKnewanonclass
, sizeof(NewAnonClassExp
))
4307 this->thisexp
= thisexp
;
4308 this->newargs
= newargs
;
4310 this->arguments
= arguments
;
4313 Expression
*NewAnonClassExp::syntaxCopy()
4315 return new NewAnonClassExp(loc
,
4316 thisexp
? thisexp
->syntaxCopy() : NULL
,
4317 arraySyntaxCopy(newargs
),
4318 (ClassDeclaration
*)cd
->syntaxCopy(NULL
),
4319 arraySyntaxCopy(arguments
));
4322 /********************** SymbolExp **************************************/
4324 SymbolExp::SymbolExp(Loc loc
, TOK op
, int size
, Declaration
*var
, bool hasOverloads
)
4325 : Expression(loc
, op
, size
)
4329 this->hasOverloads
= hasOverloads
;
4332 /********************** SymOffExp **************************************/
4334 SymOffExp::SymOffExp(Loc loc
, Declaration
*var
, dinteger_t offset
, bool hasOverloads
)
4335 : SymbolExp(loc
, TOKsymoff
, sizeof(SymOffExp
), var
,
4336 var
->isVarDeclaration() ? false : hasOverloads
)
4338 if (VarDeclaration
*v
= var
->isVarDeclaration())
4340 // FIXME: This error report will never be handled anyone.
4341 // It should be done before the SymOffExp construction.
4343 ::error(loc
, "need 'this' for address of %s", v
->toChars());
4345 this->offset
= offset
;
4348 bool SymOffExp::isBool(bool result
)
4350 return result
? true : false;
4353 /******************************** VarExp **************************/
4355 VarExp::VarExp(Loc loc
, Declaration
*var
, bool hasOverloads
)
4356 : SymbolExp(loc
, TOKvar
, sizeof(VarExp
), var
,
4357 var
->isVarDeclaration() ? false : hasOverloads
)
4359 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
4360 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
4361 this->type
= var
->type
;
4364 VarExp
*VarExp::create(Loc loc
, Declaration
*var
, bool hasOverloads
)
4366 return new VarExp(loc
, var
, hasOverloads
);
4369 bool VarExp::equals(RootObject
*o
)
4373 if (((Expression
*)o
)->op
== TOKvar
)
4375 VarExp
*ne
= (VarExp
*)o
;
4376 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
4385 bool VarExp::isLvalue()
4387 if (var
->storage_class
& (STClazy
| STCrvalue
| STCmanifest
))
4392 Expression
*VarExp::toLvalue(Scope
*, Expression
*)
4394 if (var
->storage_class
& STCmanifest
)
4396 error("manifest constant '%s' is not lvalue", var
->toChars());
4397 return new ErrorExp();
4399 if (var
->storage_class
& STClazy
)
4401 error("lazy variables cannot be lvalues");
4402 return new ErrorExp();
4404 if (var
->ident
== Id::ctfe
)
4406 error("compiler-generated variable __ctfe is not an lvalue");
4407 return new ErrorExp();
4409 if (var
->ident
== Id::dollar
) // Bugzilla 13574
4411 error("'$' is not an lvalue");
4412 return new ErrorExp();
4417 int VarExp::checkModifiable(Scope
*sc
, int flag
)
4419 //printf("VarExp::checkModifiable %s", toChars());
4421 return var
->checkModify(loc
, sc
, type
, NULL
, flag
);
4424 Expression
*VarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
4426 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
4427 if (var
->storage_class
& STCmanifest
)
4429 error("cannot modify manifest constant '%s'", toChars());
4430 return new ErrorExp();
4432 // See if this expression is a modifiable lvalue (i.e. not const)
4433 return Expression::modifiableLvalue(sc
, e
);
4437 /******************************** OverExp **************************/
4439 OverExp::OverExp(Loc loc
, OverloadSet
*s
)
4440 : Expression(loc
, TOKoverloadset
, sizeof(OverExp
))
4442 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
4447 bool OverExp::isLvalue()
4452 Expression
*OverExp::toLvalue(Scope
*, Expression
*)
4457 /******************************** TupleExp **************************/
4459 TupleExp::TupleExp(Loc loc
, Expression
*e0
, Expressions
*exps
)
4460 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
4462 //printf("TupleExp(this = %p)\n", this);
4467 TupleExp::TupleExp(Loc loc
, Expressions
*exps
)
4468 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
4470 //printf("TupleExp(this = %p)\n", this);
4475 TupleExp::TupleExp(Loc loc
, TupleDeclaration
*tup
)
4476 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
4479 this->exps
= new Expressions();
4481 this->exps
->reserve(tup
->objects
->dim
);
4482 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
4483 { RootObject
*o
= (*tup
->objects
)[i
];
4484 if (Dsymbol
*s
= getDsymbol(o
))
4486 /* If tuple element represents a symbol, translate to DsymbolExp
4487 * to supply implicit 'this' if needed later.
4489 Expression
*e
= new DsymbolExp(loc
, s
);
4490 this->exps
->push(e
);
4492 else if (o
->dyncast() == DYNCAST_EXPRESSION
)
4494 Expression
*e
= ((Expression
*)o
)->copy();
4495 e
->loc
= loc
; // Bugzilla 15669
4496 this->exps
->push(e
);
4498 else if (o
->dyncast() == DYNCAST_TYPE
)
4500 Type
*t
= (Type
*)o
;
4501 Expression
*e
= new TypeExp(loc
, t
);
4502 this->exps
->push(e
);
4506 error("%s is not an expression", o
->toChars());
4511 bool TupleExp::equals(RootObject
*o
)
4515 if (((Expression
*)o
)->op
== TOKtuple
)
4517 TupleExp
*te
= (TupleExp
*)o
;
4518 if (exps
->dim
!= te
->exps
->dim
)
4520 if ((e0
&& !e0
->equals(te
->e0
)) || (!e0
&& te
->e0
))
4522 for (size_t i
= 0; i
< exps
->dim
; i
++)
4524 Expression
*e1
= (*exps
)[i
];
4525 Expression
*e2
= (*te
->exps
)[i
];
4526 if (!e1
->equals(e2
))
4534 Expression
*TupleExp::syntaxCopy()
4536 return new TupleExp(loc
, e0
? e0
->syntaxCopy() : NULL
, arraySyntaxCopy(exps
));
4539 /******************************** FuncExp *********************************/
4541 FuncExp::FuncExp(Loc loc
, Dsymbol
*s
)
4542 : Expression(loc
, TOKfunction
, sizeof(FuncExp
))
4544 this->td
= s
->isTemplateDeclaration();
4545 this->fd
= s
->isFuncLiteralDeclaration();
4548 assert(td
->literal
);
4549 assert(td
->members
&& td
->members
->dim
== 1);
4550 fd
= (*td
->members
)[0]->isFuncLiteralDeclaration();
4552 tok
= fd
->tok
; // save original kind of function/delegate/(infer)
4556 bool FuncExp::equals(RootObject
*o
)
4560 if (o
->dyncast() != DYNCAST_EXPRESSION
)
4562 if (((Expression
*)o
)->op
== TOKfunction
)
4564 FuncExp
*fe
= (FuncExp
*)o
;
4565 return fd
== fe
->fd
;
4570 void FuncExp::genIdent(Scope
*sc
)
4572 if (fd
->ident
== Id::empty
)
4575 if (fd
->fes
) s
= "__foreachbody";
4576 else if (fd
->tok
== TOKreserved
) s
= "__lambda";
4577 else if (fd
->tok
== TOKdelegate
) s
= "__dgliteral";
4578 else s
= "__funcliteral";
4580 DsymbolTable
*symtab
;
4581 if (FuncDeclaration
*func
= sc
->parent
->isFuncDeclaration())
4583 if (func
->localsymtab
== NULL
)
4585 // Inside template constraint, symtab is not set yet.
4586 // Initialize it lazily.
4587 func
->localsymtab
= new DsymbolTable();
4589 symtab
= func
->localsymtab
;
4593 ScopeDsymbol
*sds
= sc
->parent
->isScopeDsymbol();
4596 // Inside template constraint, symtab may not be set yet.
4597 // Initialize it lazily.
4598 assert(sds
->isTemplateInstance());
4599 sds
->symtab
= new DsymbolTable();
4601 symtab
= sds
->symtab
;
4604 int num
= (int)dmd_aaLen(symtab
->tab
) + 1;
4605 Identifier
*id
= Identifier::generateId(s
, num
);
4607 if (td
) td
->ident
= id
;
4608 symtab
->insert(td
? (Dsymbol
*)td
: (Dsymbol
*)fd
);
4612 Expression
*FuncExp::syntaxCopy()
4615 return new FuncExp(loc
, td
->syntaxCopy(NULL
));
4616 else if (fd
->semanticRun
== PASSinit
)
4617 return new FuncExp(loc
, fd
->syntaxCopy(NULL
));
4618 else // Bugzilla 13481: Prevent multiple semantic analysis of lambda body.
4619 return new FuncExp(loc
, fd
);
4622 MATCH
FuncExp::matchType(Type
*to
, Scope
*sc
, FuncExp
**presult
, int flag
)
4624 //printf("FuncExp::matchType('%s'), to=%s\n", type ? type->toChars() : "null", to->toChars());
4628 TypeFunction
*tof
= NULL
;
4629 if (to
->ty
== Tdelegate
)
4631 if (tok
== TOKfunction
)
4634 error("cannot match function literal to delegate type '%s'", to
->toChars());
4635 return MATCHnomatch
;
4637 tof
= (TypeFunction
*)to
->nextOf();
4639 else if (to
->ty
== Tpointer
&& to
->nextOf()->ty
== Tfunction
)
4641 if (tok
== TOKdelegate
)
4644 error("cannot match delegate literal to function pointer type '%s'", to
->toChars());
4645 return MATCHnomatch
;
4647 tof
= (TypeFunction
*)to
->nextOf();
4656 error("cannot infer parameter types from %s", to
->toChars());
4657 return MATCHnomatch
;
4660 // Parameter types inference from 'tof'
4662 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
4663 //printf("\ttof = %s\n", tof->toChars());
4664 //printf("\ttf = %s\n", tf->toChars());
4665 size_t dim
= Parameter::dim(tf
->parameters
);
4667 if (Parameter::dim(tof
->parameters
) != dim
||
4668 tof
->varargs
!= tf
->varargs
)
4671 Objects
*tiargs
= new Objects();
4672 tiargs
->reserve(td
->parameters
->dim
);
4674 for (size_t i
= 0; i
< td
->parameters
->dim
; i
++)
4676 TemplateParameter
*tp
= (*td
->parameters
)[i
];
4678 for (; u
< dim
; u
++)
4680 Parameter
*p
= Parameter::getNth(tf
->parameters
, u
);
4681 if (p
->type
->ty
== Tident
&&
4682 ((TypeIdentifier
*)p
->type
)->ident
== tp
->ident
)
4688 Parameter
*pto
= Parameter::getNth(tof
->parameters
, u
);
4689 Type
*t
= pto
->type
;
4690 if (t
->ty
== Terror
)
4695 // Set target of return type inference
4696 if (!tf
->next
&& tof
->next
)
4699 TemplateInstance
*ti
= new TemplateInstance(loc
, td
, tiargs
);
4700 Expression
*ex
= new ScopeExp(loc
, ti
);
4701 ex
= ::semantic(ex
, td
->_scope
);
4703 // Reset inference target for the later re-semantic
4706 if (ex
->op
== TOKerror
)
4707 return MATCHnomatch
;
4708 if (ex
->op
!= TOKfunction
)
4710 return ((FuncExp
*)ex
)->matchType(to
, sc
, presult
, flag
);
4713 if (!tof
|| !tof
->next
)
4714 return MATCHnomatch
;
4716 assert(type
&& type
!= Type::tvoid
);
4717 TypeFunction
*tfx
= (TypeFunction
*)fd
->type
;
4718 bool convertMatch
= (type
->ty
!= to
->ty
);
4720 if (fd
->inferRetType
&& tfx
->next
->implicitConvTo(tof
->next
) == MATCHconvert
)
4722 /* If return type is inferred and covariant return,
4723 * tweak return statements to required return type.
4726 * class C : Object, I{}
4728 * I delegate() dg = delegate() { return new class C(); }
4730 convertMatch
= true;
4732 TypeFunction
*tfy
= new TypeFunction(tfx
->parameters
, tof
->next
, tfx
->varargs
, tfx
->linkage
, STCundefined
);
4733 tfy
->mod
= tfx
->mod
;
4734 tfy
->isnothrow
= tfx
->isnothrow
;
4735 tfy
->isnogc
= tfx
->isnogc
;
4736 tfy
->purity
= tfx
->purity
;
4737 tfy
->isproperty
= tfx
->isproperty
;
4738 tfy
->isref
= tfx
->isref
;
4739 tfy
->iswild
= tfx
->iswild
;
4740 tfy
->deco
= tfy
->merge()->deco
;
4746 if (tok
== TOKdelegate
||
4747 (tok
== TOKreserved
&& (type
->ty
== Tdelegate
||
4748 (type
->ty
== Tpointer
&& to
->ty
== Tdelegate
))))
4750 // Allow conversion from implicit function pointer to delegate
4751 tx
= new TypeDelegate(tfx
);
4752 tx
->deco
= tx
->merge()->deco
;
4756 assert(tok
== TOKfunction
||
4757 (tok
== TOKreserved
&& type
->ty
== Tpointer
));
4758 tx
= tfx
->pointerTo();
4760 //printf("\ttx = %s, to = %s\n", tx->toChars(), to->toChars());
4762 MATCH m
= tx
->implicitConvTo(to
);
4763 if (m
> MATCHnomatch
)
4765 // MATCHexact: exact type match
4766 // MATCHconst: covairiant type match (eg. attributes difference)
4767 // MATCHconvert: context conversion
4768 m
= convertMatch
? MATCHconvert
: tx
->equals(to
) ? MATCHexact
: MATCHconst
;
4772 (*presult
) = (FuncExp
*)copy();
4773 (*presult
)->type
= to
;
4775 // Bugzilla 12508: Tweak function body for covariant returns.
4776 (*presult
)->fd
->modifyReturns(sc
, tof
->next
);
4781 error("cannot implicitly convert expression (%s) of type %s to %s",
4782 toChars(), tx
->toChars(), to
->toChars());
4787 const char *FuncExp::toChars()
4789 return fd
->toChars();
4792 bool FuncExp::checkType()
4796 error("template lambda has no type");
4802 bool FuncExp::checkValue()
4806 error("template lambda has no value");
4812 /******************************** DeclarationExp **************************/
4814 DeclarationExp::DeclarationExp(Loc loc
, Dsymbol
*declaration
)
4815 : Expression(loc
, TOKdeclaration
, sizeof(DeclarationExp
))
4817 this->declaration
= declaration
;
4820 Expression
*DeclarationExp::syntaxCopy()
4822 return new DeclarationExp(loc
, declaration
->syntaxCopy(NULL
));
4825 bool DeclarationExp::hasCode()
4827 if (VarDeclaration
*vd
= declaration
->isVarDeclaration())
4829 return !(vd
->storage_class
& (STCmanifest
| STCstatic
));
4834 /************************ TypeidExp ************************************/
4840 TypeidExp::TypeidExp(Loc loc
, RootObject
*o
)
4841 : Expression(loc
, TOKtypeid
, sizeof(TypeidExp
))
4846 Expression
*TypeidExp::syntaxCopy()
4848 return new TypeidExp(loc
, objectSyntaxCopy(obj
));
4851 /************************ TraitsExp ************************************/
4853 * __traits(identifier, args...)
4856 TraitsExp::TraitsExp(Loc loc
, Identifier
*ident
, Objects
*args
)
4857 : Expression(loc
, TOKtraits
, sizeof(TraitsExp
))
4859 this->ident
= ident
;
4863 Expression
*TraitsExp::syntaxCopy()
4865 return new TraitsExp(loc
, ident
, TemplateInstance::arraySyntaxCopy(args
));
4868 /************************************************************/
4870 HaltExp::HaltExp(Loc loc
)
4871 : Expression(loc
, TOKhalt
, sizeof(HaltExp
))
4875 /************************************************************/
4877 IsExp::IsExp(Loc loc
, Type
*targ
, Identifier
*id
, TOK tok
,
4878 Type
*tspec
, TOK tok2
, TemplateParameters
*parameters
)
4879 : Expression(loc
, TOKis
, sizeof(IsExp
))
4884 this->tspec
= tspec
;
4886 this->parameters
= parameters
;
4889 Expression
*IsExp::syntaxCopy()
4891 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4892 TemplateParameters
*p
= NULL
;
4895 p
= new TemplateParameters();
4896 p
->setDim(parameters
->dim
);
4897 for (size_t i
= 0; i
< p
->dim
; i
++)
4898 (*p
)[i
] = (*parameters
)[i
]->syntaxCopy();
4900 return new IsExp(loc
,
4904 tspec
? tspec
->syntaxCopy() : NULL
,
4909 void unSpeculative(Scope
*sc
, RootObject
*o
);
4911 /************************************************************/
4913 UnaExp::UnaExp(Loc loc
, TOK op
, int size
, Expression
*e1
)
4914 : Expression(loc
, op
, size
)
4920 Expression
*UnaExp::syntaxCopy()
4922 UnaExp
*e
= (UnaExp
*)copy();
4924 e
->e1
= e
->e1
->syntaxCopy();
4928 /********************************
4929 * The type for a unary expression is incompatible.
4930 * Print error message.
4934 Expression
*UnaExp::incompatibleTypes()
4936 if (e1
->type
->toBasetype() == Type::terror
)
4939 if (e1
->op
== TOKtype
)
4941 error("incompatible type for (%s(%s)): cannot use '%s' with types",
4942 Token::toChars(op
), e1
->toChars(), Token::toChars(op
));
4946 error("incompatible type for (%s(%s)): '%s'",
4947 Token::toChars(op
), e1
->toChars(), e1
->type
->toChars());
4949 return new ErrorExp();
4952 Expression
*UnaExp::resolveLoc(Loc loc
, Scope
*sc
)
4954 e1
= e1
->resolveLoc(loc
, sc
);
4958 /************************************************************/
4960 BinExp::BinExp(Loc loc
, TOK op
, int size
, Expression
*e1
, Expression
*e2
)
4961 : Expression(loc
, op
, size
)
4970 Expression
*BinExp::syntaxCopy()
4972 BinExp
*e
= (BinExp
*)copy();
4974 e
->e1
= e
->e1
->syntaxCopy();
4975 e
->e2
= e
->e2
->syntaxCopy();
4979 Expression
*BinExp::checkOpAssignTypes(Scope
*sc
)
4981 // At that point t1 and t2 are the merged types. type is the original type of the lhs.
4982 Type
*t1
= e1
->type
;
4983 Type
*t2
= e2
->type
;
4985 // T opAssign floating yields a floating. Prevent truncating conversions (float to int).
4987 // Should we also prevent double to float (type->isfloating() && type->size() < t2 ->size()) ?
4988 if (op
== TOKaddass
|| op
== TOKminass
||
4989 op
== TOKmulass
|| op
== TOKdivass
|| op
== TOKmodass
||
4992 if ((type
->isintegral() && t2
->isfloating()))
4994 warning("%s %s %s is performing truncating conversion",
4995 type
->toChars(), Token::toChars(op
), t2
->toChars());
4999 // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
5000 if (op
== TOKmulass
|| op
== TOKdivass
|| op
== TOKmodass
)
5002 // Any multiplication by an imaginary or complex number yields a complex result.
5003 // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
5004 const char *opstr
= Token::toChars(op
);
5005 if (t1
->isreal() && t2
->iscomplex())
5007 error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
5008 t1
->toChars(), opstr
, t2
->toChars(),
5009 t1
->toChars(), opstr
, t2
->toChars());
5010 return new ErrorExp();
5012 else if (t1
->isimaginary() && t2
->iscomplex())
5014 error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
5015 t1
->toChars(), opstr
, t2
->toChars(),
5016 t1
->toChars(), opstr
, t2
->toChars());
5017 return new ErrorExp();
5019 else if ((t1
->isreal() || t1
->isimaginary()) &&
5022 error("%s %s %s is an undefined operation", t1
->toChars(), opstr
, t2
->toChars());
5023 return new ErrorExp();
5027 // generate an error if this is a nonsensical += or -=, eg real += imaginary
5028 if (op
== TOKaddass
|| op
== TOKminass
)
5030 // Addition or subtraction of a real and an imaginary is a complex result.
5031 // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
5032 if ((t1
->isreal() && (t2
->isimaginary() || t2
->iscomplex())) ||
5033 (t1
->isimaginary() && (t2
->isreal() || t2
->iscomplex())))
5035 error("%s %s %s is undefined (result is complex)",
5036 t1
->toChars(), Token::toChars(op
), t2
->toChars());
5037 return new ErrorExp();
5039 if (type
->isreal() || type
->isimaginary())
5041 assert(global
.errors
|| t2
->isfloating());
5042 e2
= e2
->castTo(sc
, t1
);
5046 if (op
== TOKmulass
)
5048 if (t2
->isfloating())
5052 if (t2
->isimaginary() || t2
->iscomplex())
5054 e2
= e2
->castTo(sc
, t1
);
5057 else if (t1
->isimaginary())
5059 if (t2
->isimaginary() || t2
->iscomplex())
5063 case Timaginary32
: t2
= Type::tfloat32
; break;
5064 case Timaginary64
: t2
= Type::tfloat64
; break;
5065 case Timaginary80
: t2
= Type::tfloat80
; break;
5069 e2
= e2
->castTo(sc
, t2
);
5074 else if (op
== TOKdivass
)
5076 if (t2
->isimaginary())
5081 // Therefore, the result is 0
5082 e2
= new CommaExp(loc
, e2
, new RealExp(loc
, CTFloat::zero
, t1
));
5084 Expression
*e
= new AssignExp(loc
, e1
, e2
);
5088 else if (t1
->isimaginary())
5093 case Timaginary32
: t3
= Type::tfloat32
; break;
5094 case Timaginary64
: t3
= Type::tfloat64
; break;
5095 case Timaginary80
: t3
= Type::tfloat80
; break;
5099 e2
= e2
->castTo(sc
, t3
);
5100 Expression
*e
= new AssignExp(loc
, e1
, e2
);
5106 else if (op
== TOKmodass
)
5108 if (t2
->iscomplex())
5110 error("cannot perform modulo complex arithmetic");
5111 return new ErrorExp();
5117 /********************************
5118 * The types for a binary expression are incompatible.
5119 * Print error message.
5123 Expression
*BinExp::incompatibleTypes()
5125 if (e1
->type
->toBasetype() == Type::terror
)
5127 if (e2
->type
->toBasetype() == Type::terror
)
5130 // CondExp uses 'a ? b : c' but we're comparing 'b : c'
5131 TOK thisOp
= (op
== TOKquestion
) ? TOKcolon
: op
;
5132 if (e1
->op
== TOKtype
|| e2
->op
== TOKtype
)
5134 error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types",
5135 e1
->toChars(), Token::toChars(thisOp
), e2
->toChars(), Token::toChars(op
));
5139 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
5140 e1
->toChars(), Token::toChars(thisOp
), e2
->toChars(),
5141 e1
->type
->toChars(), e2
->type
->toChars());
5143 return new ErrorExp();
5146 bool BinExp::checkIntegralBin()
5148 bool r1
= e1
->checkIntegral();
5149 bool r2
= e2
->checkIntegral();
5153 bool BinExp::checkArithmeticBin()
5155 bool r1
= e1
->checkArithmetic();
5156 bool r2
= e2
->checkArithmetic();
5160 /********************** BinAssignExp **************************************/
5162 BinAssignExp::BinAssignExp(Loc loc
, TOK op
, int size
, Expression
*e1
, Expression
*e2
)
5163 : BinExp(loc
, op
, size
, e1
, e2
)
5167 bool BinAssignExp::isLvalue()
5172 Expression
*BinAssignExp::toLvalue(Scope
*, Expression
*)
5174 // Lvalue-ness will be handled in glue layer.
5178 Expression
*BinAssignExp::modifiableLvalue(Scope
*sc
, Expression
*)
5180 // should check e1->checkModifiable() ?
5181 return toLvalue(sc
, this);
5184 /************************************************************/
5186 CompileExp::CompileExp(Loc loc
, Expression
*e
)
5187 : UnaExp(loc
, TOKmixin
, sizeof(CompileExp
), e
)
5191 /************************************************************/
5193 ImportExp::ImportExp(Loc loc
, Expression
*e
)
5194 : UnaExp(loc
, TOKimport
, sizeof(ImportExp
), e
)
5198 /************************************************************/
5200 AssertExp::AssertExp(Loc loc
, Expression
*e
, Expression
*msg
)
5201 : UnaExp(loc
, TOKassert
, sizeof(AssertExp
), e
)
5206 Expression
*AssertExp::syntaxCopy()
5208 return new AssertExp(loc
, e1
->syntaxCopy(), msg
? msg
->syntaxCopy() : NULL
);
5211 /************************************************************/
5213 DotIdExp::DotIdExp(Loc loc
, Expression
*e
, Identifier
*ident
)
5214 : UnaExp(loc
, TOKdotid
, sizeof(DotIdExp
), e
)
5216 this->ident
= ident
;
5217 this->wantsym
= false;
5218 this->noderef
= false;
5221 DotIdExp
*DotIdExp::create(Loc loc
, Expression
*e
, Identifier
*ident
)
5223 return new DotIdExp(loc
, e
, ident
);
5226 /********************** DotTemplateExp ***********************************/
5228 // Mainly just a placeholder
5230 DotTemplateExp::DotTemplateExp(Loc loc
, Expression
*e
, TemplateDeclaration
*td
)
5231 : UnaExp(loc
, TOKdottd
, sizeof(DotTemplateExp
), e
)
5237 /************************************************************/
5239 DotVarExp::DotVarExp(Loc loc
, Expression
*e
, Declaration
*var
, bool hasOverloads
)
5240 : UnaExp(loc
, TOKdotvar
, sizeof(DotVarExp
), e
)
5242 //printf("DotVarExp()\n");
5244 this->hasOverloads
= var
->isVarDeclaration() ? false : hasOverloads
;
5247 bool DotVarExp::isLvalue()
5252 Expression
*DotVarExp::toLvalue(Scope
*, Expression
*)
5254 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5258 /***********************************************
5259 * Mark variable v as modified if it is inside a constructor that var
5262 int modifyFieldVar(Loc loc
, Scope
*sc
, VarDeclaration
*var
, Expression
*e1
)
5264 //printf("modifyFieldVar(var = %s)\n", var->toChars());
5265 Dsymbol
*s
= sc
->func
;
5268 FuncDeclaration
*fd
= NULL
;
5270 fd
= s
->isFuncDeclaration();
5272 ((fd
->isCtorDeclaration() && var
->isField()) ||
5273 (fd
->isStaticCtorDeclaration() && !var
->isField())) &&
5274 fd
->toParent2() == var
->toParent2() &&
5275 (!e1
|| e1
->op
== TOKthis
)
5280 var
->ctorinit
= true;
5281 //printf("setting ctorinit\n");
5283 if (var
->isField() && sc
->fieldinit
&& !sc
->intypeof
)
5286 bool mustInit
= ((var
->storage_class
& STCnodefaultctor
) != 0 ||
5287 var
->type
->needsNested());
5289 size_t dim
= sc
->fieldinit_dim
;
5290 AggregateDeclaration
*ad
= fd
->isMember2();
5293 for (i
= 0; i
< dim
; i
++) // same as findFieldIndexByName in ctfeexp.c ?
5295 if (ad
->fields
[i
] == var
)
5299 unsigned fi
= sc
->fieldinit
[i
];
5301 if (fi
& CSXthis_ctor
)
5303 if (var
->type
->isMutable() && e1
->type
->isMutable())
5307 const char *modStr
= !var
->type
->isMutable() ? MODtoChars(var
->type
->mod
) : MODtoChars(e1
->type
->mod
);
5308 ::error(loc
, "%s field '%s' initialized multiple times", modStr
, var
->toChars());
5311 else if (sc
->noctor
|| (fi
& CSXlabel
))
5313 if (!mustInit
&& var
->type
->isMutable() && e1
->type
->isMutable())
5317 const char *modStr
= !var
->type
->isMutable() ? MODtoChars(var
->type
->mod
) : MODtoChars(e1
->type
->mod
);
5318 ::error(loc
, "%s field '%s' initialization is not allowed in loops or after labels", modStr
, var
->toChars());
5321 sc
->fieldinit
[i
] |= CSXthis_ctor
;
5322 if (var
->overlapped
) // Bugzilla 15258
5324 for (size_t j
= 0; j
< ad
->fields
.dim
; j
++)
5326 VarDeclaration
*v
= ad
->fields
[j
];
5327 if (v
== var
|| !var
->isOverlappedWith(v
))
5330 sc
->fieldinit
[j
] = CSXthis_ctor
;
5334 else if (fd
!= sc
->func
)
5336 if (var
->type
->isMutable())
5338 else if (sc
->func
->fes
)
5340 const char *p
= var
->isField() ? "field" : var
->kind();
5341 ::error(loc
, "%s %s '%s' initialization is not allowed in foreach loop",
5342 MODtoChars(var
->type
->mod
), p
, var
->toChars());
5346 const char *p
= var
->isField() ? "field" : var
->kind();
5347 ::error(loc
, "%s %s '%s' initialization is not allowed in nested function '%s'",
5348 MODtoChars(var
->type
->mod
), p
, var
->toChars(), sc
->func
->toChars());
5366 int DotVarExp::checkModifiable(Scope
*sc
, int flag
)
5368 //printf("DotVarExp::checkModifiable %s %s\n", toChars(), type->toChars());
5369 if (checkUnsafeAccess(sc
, this, false, !flag
))
5372 if (e1
->op
== TOKthis
)
5373 return var
->checkModify(loc
, sc
, type
, e1
, flag
);
5375 //printf("\te1 = %s\n", e1->toChars());
5376 return e1
->checkModifiable(sc
, flag
);
5379 Expression
*DotVarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5381 return Expression::modifiableLvalue(sc
, e
);
5384 /************************************************************/
5390 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc
, Expression
*e
, Identifier
*name
, Objects
*tiargs
)
5391 : UnaExp(loc
, TOKdotti
, sizeof(DotTemplateInstanceExp
), e
)
5393 //printf("DotTemplateInstanceExp()\n");
5394 this->ti
= new TemplateInstance(loc
, name
);
5395 this->ti
->tiargs
= tiargs
;
5398 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc
, Expression
*e
, TemplateInstance
*ti
)
5399 : UnaExp(loc
, TOKdotti
, sizeof(DotTemplateInstanceExp
), e
)
5404 Expression
*DotTemplateInstanceExp::syntaxCopy()
5406 return new DotTemplateInstanceExp(loc
,
5409 TemplateInstance::arraySyntaxCopy(ti
->tiargs
));
5412 bool DotTemplateInstanceExp::findTempDecl(Scope
*sc
)
5417 Expression
*e
= new DotIdExp(loc
, e1
, ti
->name
);
5418 e
= semantic(e
, sc
);
5419 if (e
->op
== TOKdot
)
5420 e
= ((DotExp
*)e
)->e2
;
5425 case TOKoverloadset
: s
= ((OverExp
*)e
)->vars
; break;
5426 case TOKdottd
: s
= ((DotTemplateExp
*)e
)->td
; break;
5427 case TOKscope
: s
= ((ScopeExp
*)e
)->sds
; break;
5428 case TOKdotvar
: s
= ((DotVarExp
*)e
)->var
; break;
5429 case TOKvar
: s
= ((VarExp
*)e
)->var
; break;
5430 default: return false;
5432 return ti
->updateTempDecl(sc
, s
);
5435 /************************************************************/
5437 DelegateExp::DelegateExp(Loc loc
, Expression
*e
, FuncDeclaration
*f
, bool hasOverloads
)
5438 : UnaExp(loc
, TOKdelegate
, sizeof(DelegateExp
), e
)
5441 this->hasOverloads
= hasOverloads
;
5444 /************************************************************/
5446 DotTypeExp::DotTypeExp(Loc loc
, Expression
*e
, Dsymbol
*s
)
5447 : UnaExp(loc
, TOKdottype
, sizeof(DotTypeExp
), e
)
5453 /************************************************************/
5455 CallExp::CallExp(Loc loc
, Expression
*e
, Expressions
*exps
)
5456 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5458 this->arguments
= exps
;
5460 this->directcall
= false;
5463 CallExp::CallExp(Loc loc
, Expression
*e
)
5464 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5466 this->arguments
= NULL
;
5468 this->directcall
= false;
5471 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
)
5472 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5474 Expressions
*arguments
= new Expressions();
5477 arguments
->setDim(1);
5478 (*arguments
)[0] = earg1
;
5480 this->arguments
= arguments
;
5482 this->directcall
= false;
5485 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
, Expression
*earg2
)
5486 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5488 Expressions
*arguments
= new Expressions();
5489 arguments
->setDim(2);
5490 (*arguments
)[0] = earg1
;
5491 (*arguments
)[1] = earg2
;
5493 this->arguments
= arguments
;
5495 this->directcall
= false;
5498 CallExp
*CallExp::create(Loc loc
, Expression
*e
, Expressions
*exps
)
5500 return new CallExp(loc
, e
, exps
);
5503 CallExp
*CallExp::create(Loc loc
, Expression
*e
)
5505 return new CallExp(loc
, e
);
5508 CallExp
*CallExp::create(Loc loc
, Expression
*e
, Expression
*earg1
)
5510 return new CallExp(loc
, e
, earg1
);
5513 Expression
*CallExp::syntaxCopy()
5515 return new CallExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
5518 bool CallExp::isLvalue()
5520 Type
*tb
= e1
->type
->toBasetype();
5521 if (tb
->ty
== Tdelegate
|| tb
->ty
== Tpointer
)
5523 if (tb
->ty
== Tfunction
&& ((TypeFunction
*)tb
)->isref
)
5525 if (e1
->op
== TOKdotvar
)
5526 if (((DotVarExp
*)e1
)->var
->isCtorDeclaration())
5528 return true; // function returns a reference
5533 Expression
*CallExp::toLvalue(Scope
*sc
, Expression
*e
)
5537 return Expression::toLvalue(sc
, e
);
5540 Expression
*CallExp::addDtorHook(Scope
*sc
)
5542 /* Only need to add dtor hook if it's a type that needs destruction.
5543 * Use same logic as VarDeclaration::callScopeDtor()
5546 if (e1
->type
&& e1
->type
->ty
== Tfunction
)
5548 TypeFunction
*tf
= (TypeFunction
*)e1
->type
;
5553 Type
*tv
= type
->baseElemOf();
5554 if (tv
->ty
== Tstruct
)
5556 TypeStruct
*ts
= (TypeStruct
*)tv
;
5557 StructDeclaration
*sd
= ts
->sym
;
5560 /* Type needs destruction, so declare a tmp
5561 * which the back end will recognize and call dtor on
5563 VarDeclaration
*tmp
= copyToTemp(0, "__tmpfordtor", this);
5564 DeclarationExp
*de
= new DeclarationExp(loc
, tmp
);
5565 VarExp
*ve
= new VarExp(loc
, tmp
);
5566 Expression
*e
= new CommaExp(loc
, de
, ve
);
5567 e
= semantic(e
, sc
);
5574 FuncDeclaration
*isFuncAddress(Expression
*e
, bool *hasOverloads
= NULL
)
5576 if (e
->op
== TOKaddress
)
5578 Expression
*ae1
= ((AddrExp
*)e
)->e1
;
5579 if (ae1
->op
== TOKvar
)
5581 VarExp
*ve
= (VarExp
*)ae1
;
5583 *hasOverloads
= ve
->hasOverloads
;
5584 return ve
->var
->isFuncDeclaration();
5586 if (ae1
->op
== TOKdotvar
)
5588 DotVarExp
*dve
= (DotVarExp
*)ae1
;
5590 *hasOverloads
= dve
->hasOverloads
;
5591 return dve
->var
->isFuncDeclaration();
5596 if (e
->op
== TOKsymoff
)
5598 SymOffExp
*soe
= (SymOffExp
*)e
;
5600 *hasOverloads
= soe
->hasOverloads
;
5601 return soe
->var
->isFuncDeclaration();
5603 if (e
->op
== TOKdelegate
)
5605 DelegateExp
*dge
= (DelegateExp
*)e
;
5607 *hasOverloads
= dge
->hasOverloads
;
5608 return dge
->func
->isFuncDeclaration();
5614 /************************************************************/
5616 AddrExp::AddrExp(Loc loc
, Expression
*e
)
5617 : UnaExp(loc
, TOKaddress
, sizeof(AddrExp
), e
)
5621 AddrExp::AddrExp(Loc loc
, Expression
*e
, Type
*t
)
5622 : UnaExp(loc
, TOKaddress
, sizeof(AddrExp
), e
)
5627 /************************************************************/
5629 PtrExp::PtrExp(Loc loc
, Expression
*e
)
5630 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
5633 // type = ((TypePointer *)e->type)->next;
5636 PtrExp::PtrExp(Loc loc
, Expression
*e
, Type
*t
)
5637 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
5642 bool PtrExp::isLvalue()
5647 Expression
*PtrExp::toLvalue(Scope
*, Expression
*)
5652 int PtrExp::checkModifiable(Scope
*sc
, int flag
)
5654 if (e1
->op
== TOKsymoff
)
5655 { SymOffExp
*se
= (SymOffExp
*)e1
;
5656 return se
->var
->checkModify(loc
, sc
, type
, NULL
, flag
);
5658 else if (e1
->op
== TOKaddress
)
5660 AddrExp
*ae
= (AddrExp
*)e1
;
5661 return ae
->e1
->checkModifiable(sc
, flag
);
5666 Expression
*PtrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5668 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
5669 return Expression::modifiableLvalue(sc
, e
);
5672 /************************************************************/
5674 NegExp::NegExp(Loc loc
, Expression
*e
)
5675 : UnaExp(loc
, TOKneg
, sizeof(NegExp
), e
)
5679 /************************************************************/
5681 UAddExp::UAddExp(Loc loc
, Expression
*e
)
5682 : UnaExp(loc
, TOKuadd
, sizeof(UAddExp
), e
)
5686 /************************************************************/
5688 ComExp::ComExp(Loc loc
, Expression
*e
)
5689 : UnaExp(loc
, TOKtilde
, sizeof(ComExp
), e
)
5693 /************************************************************/
5695 NotExp::NotExp(Loc loc
, Expression
*e
)
5696 : UnaExp(loc
, TOKnot
, sizeof(NotExp
), e
)
5700 /************************************************************/
5702 DeleteExp::DeleteExp(Loc loc
, Expression
*e
, bool isRAII
)
5703 : UnaExp(loc
, TOKdelete
, sizeof(DeleteExp
), e
)
5705 this->isRAII
= isRAII
;
5708 Expression
*DeleteExp::toBoolean(Scope
*)
5710 error("delete does not give a boolean result");
5711 return new ErrorExp();
5714 /************************************************************/
5716 CastExp::CastExp(Loc loc
, Expression
*e
, Type
*t
)
5717 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
5720 this->mod
= (unsigned char)~0;
5723 /* For cast(const) and cast(immutable)
5725 CastExp::CastExp(Loc loc
, Expression
*e
, unsigned char mod
)
5726 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
5732 Expression
*CastExp::syntaxCopy()
5734 return to
? new CastExp(loc
, e1
->syntaxCopy(), to
->syntaxCopy())
5735 : new CastExp(loc
, e1
->syntaxCopy(), mod
);
5738 /************************************************************/
5740 VectorExp::VectorExp(Loc loc
, Expression
*e
, Type
*t
)
5741 : UnaExp(loc
, TOKvector
, sizeof(VectorExp
), e
)
5743 assert(t
->ty
== Tvector
);
5744 to
= (TypeVector
*)t
;
5748 VectorExp
*VectorExp::create(Loc loc
, Expression
*e
, Type
*t
)
5750 return new VectorExp(loc
, e
, t
);
5753 Expression
*VectorExp::syntaxCopy()
5755 return new VectorExp(loc
, e1
->syntaxCopy(), to
->syntaxCopy());
5758 /************************************************************/
5760 SliceExp::SliceExp(Loc loc
, Expression
*e1
, IntervalExp
*ie
)
5761 : UnaExp(loc
, TOKslice
, sizeof(SliceExp
), e1
)
5763 this->upr
= ie
? ie
->upr
: NULL
;
5764 this->lwr
= ie
? ie
->lwr
: NULL
;
5766 upperIsInBounds
= false;
5767 lowerIsLessThanUpper
= false;
5771 SliceExp::SliceExp(Loc loc
, Expression
*e1
, Expression
*lwr
, Expression
*upr
)
5772 : UnaExp(loc
, TOKslice
, sizeof(SliceExp
), e1
)
5777 upperIsInBounds
= false;
5778 lowerIsLessThanUpper
= false;
5782 Expression
*SliceExp::syntaxCopy()
5784 SliceExp
*se
= new SliceExp(loc
, e1
->syntaxCopy(),
5785 lwr
? lwr
->syntaxCopy() : NULL
,
5786 upr
? upr
->syntaxCopy() : NULL
);
5787 se
->lengthVar
= this->lengthVar
; // bug7871
5791 int SliceExp::checkModifiable(Scope
*sc
, int flag
)
5793 //printf("SliceExp::checkModifiable %s\n", toChars());
5794 if (e1
->type
->ty
== Tsarray
||
5795 (e1
->op
== TOKindex
&& e1
->type
->ty
!= Tarray
) ||
5798 return e1
->checkModifiable(sc
, flag
);
5803 bool SliceExp::isLvalue()
5805 /* slice expression is rvalue in default, but
5806 * conversion to reference of static array is only allowed.
5808 return (type
&& type
->toBasetype()->ty
== Tsarray
);
5811 Expression
*SliceExp::toLvalue(Scope
*sc
, Expression
*e
)
5813 //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
5814 return (type
&& type
->toBasetype()->ty
== Tsarray
)
5815 ? this : Expression::toLvalue(sc
, e
);
5818 Expression
*SliceExp::modifiableLvalue(Scope
*, Expression
*)
5820 error("slice expression %s is not a modifiable lvalue", toChars());
5824 bool SliceExp::isBool(bool result
)
5826 return e1
->isBool(result
);
5829 /********************** ArrayLength **************************************/
5831 ArrayLengthExp::ArrayLengthExp(Loc loc
, Expression
*e1
)
5832 : UnaExp(loc
, TOKarraylength
, sizeof(ArrayLengthExp
), e1
)
5836 Expression
*opAssignToOp(Loc loc
, TOK op
, Expression
*e1
, Expression
*e2
)
5841 case TOKaddass
: e
= new AddExp(loc
, e1
, e2
); break;
5842 case TOKminass
: e
= new MinExp(loc
, e1
, e2
); break;
5843 case TOKmulass
: e
= new MulExp(loc
, e1
, e2
); break;
5844 case TOKdivass
: e
= new DivExp(loc
, e1
, e2
); break;
5845 case TOKmodass
: e
= new ModExp(loc
, e1
, e2
); break;
5846 case TOKandass
: e
= new AndExp(loc
, e1
, e2
); break;
5847 case TOKorass
: e
= new OrExp (loc
, e1
, e2
); break;
5848 case TOKxorass
: e
= new XorExp(loc
, e1
, e2
); break;
5849 case TOKshlass
: e
= new ShlExp(loc
, e1
, e2
); break;
5850 case TOKshrass
: e
= new ShrExp(loc
, e1
, e2
); break;
5851 case TOKushrass
: e
= new UshrExp(loc
, e1
, e2
); break;
5857 /*********************
5859 * array.length op= e2
5861 * array.length = array.length op e2
5863 * auto tmp = &array;
5864 * (*tmp).length = (*tmp).length op e2
5867 Expression
*ArrayLengthExp::rewriteOpAssign(BinExp
*exp
)
5871 assert(exp
->e1
->op
== TOKarraylength
);
5872 ArrayLengthExp
*ale
= (ArrayLengthExp
*)exp
->e1
;
5873 if (ale
->e1
->op
== TOKvar
)
5875 e
= opAssignToOp(exp
->loc
, exp
->op
, ale
, exp
->e2
);
5876 e
= new AssignExp(exp
->loc
, ale
->syntaxCopy(), e
);
5880 /* auto tmp = &array;
5881 * (*tmp).length = (*tmp).length op e2
5883 VarDeclaration
*tmp
= copyToTemp(0, "__arraylength", new AddrExp(ale
->loc
, ale
->e1
));
5885 Expression
*e1
= new ArrayLengthExp(ale
->loc
, new PtrExp(ale
->loc
, new VarExp(ale
->loc
, tmp
)));
5886 Expression
*elvalue
= e1
->syntaxCopy();
5887 e
= opAssignToOp(exp
->loc
, exp
->op
, e1
, exp
->e2
);
5888 e
= new AssignExp(exp
->loc
, elvalue
, e
);
5889 e
= new CommaExp(exp
->loc
, new DeclarationExp(ale
->loc
, tmp
), e
);
5894 /*********************** IntervalExp ********************************/
5896 // Mainly just a placeholder
5898 IntervalExp::IntervalExp(Loc loc
, Expression
*lwr
, Expression
*upr
)
5899 : Expression(loc
, TOKinterval
, sizeof(IntervalExp
))
5905 Expression
*IntervalExp::syntaxCopy()
5907 return new IntervalExp(loc
, lwr
->syntaxCopy(), upr
->syntaxCopy());
5910 /********************** DelegatePtrExp **************************************/
5912 DelegatePtrExp::DelegatePtrExp(Loc loc
, Expression
*e1
)
5913 : UnaExp(loc
, TOKdelegateptr
, sizeof(DelegatePtrExp
), e1
)
5917 bool DelegatePtrExp::isLvalue()
5919 return e1
->isLvalue();
5922 Expression
*DelegatePtrExp::toLvalue(Scope
*sc
, Expression
*e
)
5924 e1
= e1
->toLvalue(sc
, e
);
5928 Expression
*DelegatePtrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5930 if (sc
->func
->setUnsafe())
5932 error("cannot modify delegate pointer in @safe code %s", toChars());
5933 return new ErrorExp();
5935 return Expression::modifiableLvalue(sc
, e
);
5938 /********************** DelegateFuncptrExp **************************************/
5940 DelegateFuncptrExp::DelegateFuncptrExp(Loc loc
, Expression
*e1
)
5941 : UnaExp(loc
, TOKdelegatefuncptr
, sizeof(DelegateFuncptrExp
), e1
)
5945 bool DelegateFuncptrExp::isLvalue()
5947 return e1
->isLvalue();
5950 Expression
*DelegateFuncptrExp::toLvalue(Scope
*sc
, Expression
*e
)
5952 e1
= e1
->toLvalue(sc
, e
);
5956 Expression
*DelegateFuncptrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5958 if (sc
->func
->setUnsafe())
5960 error("cannot modify delegate function pointer in @safe code %s", toChars());
5961 return new ErrorExp();
5963 return Expression::modifiableLvalue(sc
, e
);
5966 /*********************** ArrayExp *************************************/
5968 // e1 [ i1, i2, i3, ... ]
5970 ArrayExp::ArrayExp(Loc loc
, Expression
*e1
, Expression
*index
)
5971 : UnaExp(loc
, TOKarray
, sizeof(ArrayExp
), e1
)
5973 arguments
= new Expressions();
5975 arguments
->push(index
);
5977 currentDimension
= 0;
5980 ArrayExp::ArrayExp(Loc loc
, Expression
*e1
, Expressions
*args
)
5981 : UnaExp(loc
, TOKarray
, sizeof(ArrayExp
), e1
)
5985 currentDimension
= 0;
5988 Expression
*ArrayExp::syntaxCopy()
5990 ArrayExp
*ae
= new ArrayExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
5991 ae
->lengthVar
= this->lengthVar
; // bug7871
5995 bool ArrayExp::isLvalue()
5997 if (type
&& type
->toBasetype()->ty
== Tvoid
)
6002 Expression
*ArrayExp::toLvalue(Scope
*, Expression
*)
6004 if (type
&& type
->toBasetype()->ty
== Tvoid
)
6005 error("voids have no value");
6009 /************************* DotExp ***********************************/
6011 DotExp::DotExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6012 : BinExp(loc
, TOKdot
, sizeof(DotExp
), e1
, e2
)
6016 /************************* CommaExp ***********************************/
6018 CommaExp::CommaExp(Loc loc
, Expression
*e1
, Expression
*e2
, bool generated
)
6019 : BinExp(loc
, TOKcomma
, sizeof(CommaExp
), e1
, e2
)
6021 isGenerated
= generated
;
6022 allowCommaExp
= generated
;
6025 bool CommaExp::isLvalue()
6027 return e2
->isLvalue();
6030 Expression
*CommaExp::toLvalue(Scope
*sc
, Expression
*)
6032 e2
= e2
->toLvalue(sc
, NULL
);
6036 int CommaExp::checkModifiable(Scope
*sc
, int flag
)
6038 return e2
->checkModifiable(sc
, flag
);
6041 Expression
*CommaExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6043 e2
= e2
->modifiableLvalue(sc
, e
);
6047 bool CommaExp::isBool(bool result
)
6049 return e2
->isBool(result
);
6052 Expression
*CommaExp::toBoolean(Scope
*sc
)
6054 Expression
*ex2
= e2
->toBoolean(sc
);
6055 if (ex2
->op
== TOKerror
)
6062 Expression
*CommaExp::addDtorHook(Scope
*sc
)
6064 e2
= e2
->addDtorHook(sc
);
6068 /************************** IndexExp **********************************/
6072 IndexExp::IndexExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6073 : BinExp(loc
, TOKindex
, sizeof(IndexExp
), e1
, e2
)
6075 //printf("IndexExp::IndexExp('%s')\n", toChars());
6077 modifiable
= false; // assume it is an rvalue
6078 indexIsInBounds
= false;
6081 Expression
*IndexExp::syntaxCopy()
6083 IndexExp
*ie
= new IndexExp(loc
, e1
->syntaxCopy(), e2
->syntaxCopy());
6084 ie
->lengthVar
= this->lengthVar
; // bug7871
6088 bool IndexExp::isLvalue()
6093 Expression
*IndexExp::toLvalue(Scope
*, Expression
*)
6098 int IndexExp::checkModifiable(Scope
*sc
, int flag
)
6100 if (e1
->type
->ty
== Tsarray
||
6101 e1
->type
->ty
== Taarray
||
6102 (e1
->op
== TOKindex
&& e1
->type
->ty
!= Tarray
) ||
6105 return e1
->checkModifiable(sc
, flag
);
6110 Expression
*IndexExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6112 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
6113 Expression
*ex
= markSettingAAElem();
6114 if (ex
->op
== TOKerror
)
6117 return Expression::modifiableLvalue(sc
, e
);
6120 Expression
*IndexExp::markSettingAAElem()
6122 if (e1
->type
->toBasetype()->ty
== Taarray
)
6124 Type
*t2b
= e2
->type
->toBasetype();
6125 if (t2b
->ty
== Tarray
&& t2b
->nextOf()->isMutable())
6127 error("associative arrays can only be assigned values with immutable keys, not %s", e2
->type
->toChars());
6128 return new ErrorExp();
6132 if (e1
->op
== TOKindex
)
6134 Expression
*ex
= ((IndexExp
*)e1
)->markSettingAAElem();
6135 if (ex
->op
== TOKerror
)
6143 /************************* PostExp ***********************************/
6145 PostExp::PostExp(TOK op
, Loc loc
, Expression
*e
)
6146 : BinExp(loc
, op
, sizeof(PostExp
), e
,
6147 new IntegerExp(loc
, 1, Type::tint32
))
6151 /************************* PreExp ***********************************/
6153 PreExp::PreExp(TOK op
, Loc loc
, Expression
*e
)
6154 : UnaExp(loc
, op
, sizeof(PreExp
), e
)
6158 /************************************************************/
6160 /* op can be TOKassign, TOKconstruct, or TOKblit */
6162 AssignExp::AssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6163 : BinExp(loc
, TOKassign
, sizeof(AssignExp
), e1
, e2
)
6168 bool AssignExp::isLvalue()
6170 // Array-op 'x[] = y[]' should make an rvalue.
6171 // Setting array length 'x.length = v' should make an rvalue.
6172 if (e1
->op
== TOKslice
||
6173 e1
->op
== TOKarraylength
)
6180 Expression
*AssignExp::toLvalue(Scope
*sc
, Expression
*ex
)
6182 if (e1
->op
== TOKslice
||
6183 e1
->op
== TOKarraylength
)
6185 return Expression::toLvalue(sc
, ex
);
6188 /* In front-end level, AssignExp should make an lvalue of e1.
6189 * Taking the address of e1 will be handled in low level layer,
6190 * so this function does nothing.
6195 Expression
*AssignExp::toBoolean(Scope
*)
6199 // are usually mistakes.
6201 error("assignment cannot be used as a condition, perhaps == was meant?");
6202 return new ErrorExp();
6205 /************************************************************/
6207 ConstructExp::ConstructExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6208 : AssignExp(loc
, e1
, e2
)
6213 ConstructExp::ConstructExp(Loc loc
, VarDeclaration
*v
, Expression
*e2
)
6214 : AssignExp(loc
, new VarExp(loc
, v
), e2
)
6216 assert(v
->type
&& e1
->type
);
6219 if (v
->storage_class
& (STCref
| STCout
))
6220 memset
|= referenceInit
;
6223 /************************************************************/
6225 BlitExp::BlitExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6226 : AssignExp(loc
, e1
, e2
)
6231 BlitExp::BlitExp(Loc loc
, VarDeclaration
*v
, Expression
*e2
)
6232 : AssignExp(loc
, new VarExp(loc
, v
), e2
)
6234 assert(v
->type
&& e1
->type
);
6237 if (v
->storage_class
& (STCref
| STCout
))
6238 memset
|= referenceInit
;
6241 /************************************************************/
6243 AddAssignExp::AddAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6244 : BinAssignExp(loc
, TOKaddass
, sizeof(AddAssignExp
), e1
, e2
)
6248 /************************************************************/
6250 MinAssignExp::MinAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6251 : BinAssignExp(loc
, TOKminass
, sizeof(MinAssignExp
), e1
, e2
)
6255 /************************************************************/
6257 CatAssignExp::CatAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6258 : BinAssignExp(loc
, TOKcatass
, sizeof(CatAssignExp
), e1
, e2
)
6262 /************************************************************/
6264 MulAssignExp::MulAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6265 : BinAssignExp(loc
, TOKmulass
, sizeof(MulAssignExp
), e1
, e2
)
6269 /************************************************************/
6271 DivAssignExp::DivAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6272 : BinAssignExp(loc
, TOKdivass
, sizeof(DivAssignExp
), e1
, e2
)
6276 /************************************************************/
6278 ModAssignExp::ModAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6279 : BinAssignExp(loc
, TOKmodass
, sizeof(ModAssignExp
), e1
, e2
)
6283 /************************************************************/
6285 ShlAssignExp::ShlAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6286 : BinAssignExp(loc
, TOKshlass
, sizeof(ShlAssignExp
), e1
, e2
)
6290 /************************************************************/
6292 ShrAssignExp::ShrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6293 : BinAssignExp(loc
, TOKshrass
, sizeof(ShrAssignExp
), e1
, e2
)
6297 /************************************************************/
6299 UshrAssignExp::UshrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6300 : BinAssignExp(loc
, TOKushrass
, sizeof(UshrAssignExp
), e1
, e2
)
6304 /************************************************************/
6306 AndAssignExp::AndAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6307 : BinAssignExp(loc
, TOKandass
, sizeof(AndAssignExp
), e1
, e2
)
6311 /************************************************************/
6313 OrAssignExp::OrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6314 : BinAssignExp(loc
, TOKorass
, sizeof(OrAssignExp
), e1
, e2
)
6318 /************************************************************/
6320 XorAssignExp::XorAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6321 : BinAssignExp(loc
, TOKxorass
, sizeof(XorAssignExp
), e1
, e2
)
6325 /***************** PowAssignExp *******************************************/
6327 PowAssignExp::PowAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6328 : BinAssignExp(loc
, TOKpowass
, sizeof(PowAssignExp
), e1
, e2
)
6332 /************************* AddExp *****************************/
6334 AddExp::AddExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6335 : BinExp(loc
, TOKadd
, sizeof(AddExp
), e1
, e2
)
6339 /************************************************************/
6341 MinExp::MinExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6342 : BinExp(loc
, TOKmin
, sizeof(MinExp
), e1
, e2
)
6346 /************************* CatExp *****************************/
6348 CatExp::CatExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6349 : BinExp(loc
, TOKcat
, sizeof(CatExp
), e1
, e2
)
6353 /************************************************************/
6355 MulExp::MulExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6356 : BinExp(loc
, TOKmul
, sizeof(MulExp
), e1
, e2
)
6360 /************************************************************/
6362 DivExp::DivExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6363 : BinExp(loc
, TOKdiv
, sizeof(DivExp
), e1
, e2
)
6367 /************************************************************/
6369 ModExp::ModExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6370 : BinExp(loc
, TOKmod
, sizeof(ModExp
), e1
, e2
)
6374 /************************************************************/
6376 PowExp::PowExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6377 : BinExp(loc
, TOKpow
, sizeof(PowExp
), e1
, e2
)
6381 /************************************************************/
6383 ShlExp::ShlExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6384 : BinExp(loc
, TOKshl
, sizeof(ShlExp
), e1
, e2
)
6388 /************************************************************/
6390 ShrExp::ShrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6391 : BinExp(loc
, TOKshr
, sizeof(ShrExp
), e1
, e2
)
6395 /************************************************************/
6397 UshrExp::UshrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6398 : BinExp(loc
, TOKushr
, sizeof(UshrExp
), e1
, e2
)
6402 /************************************************************/
6404 AndExp::AndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6405 : BinExp(loc
, TOKand
, sizeof(AndExp
), e1
, e2
)
6409 /************************************************************/
6411 OrExp::OrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6412 : BinExp(loc
, TOKor
, sizeof(OrExp
), e1
, e2
)
6416 /************************************************************/
6418 XorExp::XorExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6419 : BinExp(loc
, TOKxor
, sizeof(XorExp
), e1
, e2
)
6423 /************************************************************/
6425 OrOrExp::OrOrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6426 : BinExp(loc
, TOKoror
, sizeof(OrOrExp
), e1
, e2
)
6430 Expression
*OrOrExp::toBoolean(Scope
*sc
)
6432 Expression
*ex2
= e2
->toBoolean(sc
);
6433 if (ex2
->op
== TOKerror
)
6439 /************************************************************/
6441 AndAndExp::AndAndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6442 : BinExp(loc
, TOKandand
, sizeof(AndAndExp
), e1
, e2
)
6446 Expression
*AndAndExp::toBoolean(Scope
*sc
)
6448 Expression
*ex2
= e2
->toBoolean(sc
);
6449 if (ex2
->op
== TOKerror
)
6455 /************************************************************/
6457 InExp::InExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6458 : BinExp(loc
, TOKin
, sizeof(InExp
), e1
, e2
)
6462 /************************************************************/
6464 /* This deletes the key e1 from the associative array e2
6467 RemoveExp::RemoveExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6468 : BinExp(loc
, TOKremove
, sizeof(RemoveExp
), e1
, e2
)
6473 /************************************************************/
6475 CmpExp::CmpExp(TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
6476 : BinExp(loc
, op
, sizeof(CmpExp
), e1
, e2
)
6480 /************************************************************/
6482 EqualExp::EqualExp(TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
6483 : BinExp(loc
, op
, sizeof(EqualExp
), e1
, e2
)
6485 assert(op
== TOKequal
|| op
== TOKnotequal
);
6488 /************************************************************/
6490 IdentityExp::IdentityExp(TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
6491 : BinExp(loc
, op
, sizeof(IdentityExp
), e1
, e2
)
6495 /****************************************************************/
6497 CondExp::CondExp(Loc loc
, Expression
*econd
, Expression
*e1
, Expression
*e2
)
6498 : BinExp(loc
, TOKquestion
, sizeof(CondExp
), e1
, e2
)
6500 this->econd
= econd
;
6503 Expression
*CondExp::syntaxCopy()
6505 return new CondExp(loc
, econd
->syntaxCopy(), e1
->syntaxCopy(), e2
->syntaxCopy());
6508 void CondExp::hookDtors(Scope
*sc
)
6510 class DtorVisitor
: public StoppableVisitor
6515 VarDeclaration
*vcond
;
6518 DtorVisitor(Scope
*sc
, CondExp
*ce
)
6525 void visit(Expression
*)
6527 //printf("(e = %s)\n", e->toChars());
6530 void visit(DeclarationExp
*e
)
6532 VarDeclaration
*v
= e
->declaration
->isVarDeclaration();
6533 if (v
&& !v
->isDataseg())
6537 ExpInitializer
*ei
= v
->_init
->isExpInitializer();
6539 ei
->exp
->accept(this);
6542 if (v
->needsScopeDtor())
6546 vcond
= copyToTemp(STCvolatile
, "__cond", ce
->econd
);
6547 vcond
->semantic(sc
);
6549 Expression
*de
= new DeclarationExp(ce
->econd
->loc
, vcond
);
6550 de
= semantic(de
, sc
);
6552 Expression
*ve
= new VarExp(ce
->econd
->loc
, vcond
);
6553 ce
->econd
= Expression::combine(de
, ve
);
6556 //printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6557 Expression
*ve
= new VarExp(vcond
->loc
, vcond
);
6559 v
->edtor
= new AndAndExp(v
->edtor
->loc
, ve
, v
->edtor
);
6561 v
->edtor
= new OrOrExp(v
->edtor
->loc
, ve
, v
->edtor
);
6562 v
->edtor
= semantic(v
->edtor
, sc
);
6563 //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6569 DtorVisitor
v(sc
, this);
6570 //printf("+%s\n", toChars());
6571 v
.isThen
= true; walkPostorder(e1
, &v
);
6572 v
.isThen
= false; walkPostorder(e2
, &v
);
6573 //printf("-%s\n", toChars());
6576 bool CondExp::isLvalue()
6578 return e1
->isLvalue() && e2
->isLvalue();
6582 Expression
*CondExp::toLvalue(Scope
*sc
, Expression
*)
6584 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
6585 CondExp
*e
= (CondExp
*)copy();
6586 e
->e1
= e1
->toLvalue(sc
, NULL
)->addressOf();
6587 e
->e2
= e2
->toLvalue(sc
, NULL
)->addressOf();
6588 e
->type
= type
->pointerTo();
6589 return new PtrExp(loc
, e
, type
);
6592 int CondExp::checkModifiable(Scope
*sc
, int flag
)
6594 return e1
->checkModifiable(sc
, flag
) && e2
->checkModifiable(sc
, flag
);
6597 Expression
*CondExp::modifiableLvalue(Scope
*sc
, Expression
*)
6599 //error("conditional expression %s is not a modifiable lvalue", toChars());
6600 e1
= e1
->modifiableLvalue(sc
, e1
);
6601 e2
= e2
->modifiableLvalue(sc
, e2
);
6602 return toLvalue(sc
, this);
6605 Expression
*CondExp::toBoolean(Scope
*sc
)
6607 Expression
*ex1
= e1
->toBoolean(sc
);
6608 Expression
*ex2
= e2
->toBoolean(sc
);
6609 if (ex1
->op
== TOKerror
)
6611 if (ex2
->op
== TOKerror
)
6618 /****************************************************************/
6620 DefaultInitExp::DefaultInitExp(Loc loc
, TOK subop
, int size
)
6621 : Expression(loc
, TOKdefault
, size
)
6623 this->subop
= subop
;
6626 /****************************************************************/
6628 FileInitExp::FileInitExp(Loc loc
, TOK tok
)
6629 : DefaultInitExp(loc
, tok
, sizeof(FileInitExp
))
6633 Expression
*FileInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6635 //printf("FileInitExp::resolve() %s\n", toChars());
6636 const char *s
= loc
.filename
? loc
.filename
: sc
->_module
->ident
->toChars();
6637 if (subop
== TOKfilefullpath
)
6638 s
= FileName::combine(sc
->_module
->srcfilePath
, s
);
6639 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6640 e
= semantic(e
, sc
);
6641 e
= e
->castTo(sc
, type
);
6645 /****************************************************************/
6647 LineInitExp::LineInitExp(Loc loc
)
6648 : DefaultInitExp(loc
, TOKline
, sizeof(LineInitExp
))
6652 Expression
*LineInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6654 Expression
*e
= new IntegerExp(loc
, loc
.linnum
, Type::tint32
);
6655 e
= e
->castTo(sc
, type
);
6659 /****************************************************************/
6661 ModuleInitExp::ModuleInitExp(Loc loc
)
6662 : DefaultInitExp(loc
, TOKmodulestring
, sizeof(ModuleInitExp
))
6666 Expression
*ModuleInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6670 s
= sc
->callsc
->_module
->toPrettyChars();
6672 s
= sc
->_module
->toPrettyChars();
6673 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6674 e
= semantic(e
, sc
);
6675 e
= e
->castTo(sc
, type
);
6679 /****************************************************************/
6681 FuncInitExp::FuncInitExp(Loc loc
)
6682 : DefaultInitExp(loc
, TOKfuncstring
, sizeof(FuncInitExp
))
6686 Expression
*FuncInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6689 if (sc
->callsc
&& sc
->callsc
->func
)
6690 s
= sc
->callsc
->func
->Dsymbol::toPrettyChars();
6692 s
= sc
->func
->Dsymbol::toPrettyChars();
6695 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6696 e
= semantic(e
, sc
);
6697 e
= e
->castTo(sc
, type
);
6701 /****************************************************************/
6703 PrettyFuncInitExp::PrettyFuncInitExp(Loc loc
)
6704 : DefaultInitExp(loc
, TOKprettyfunc
, sizeof(PrettyFuncInitExp
))
6708 Expression
*PrettyFuncInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6710 FuncDeclaration
*fd
;
6711 if (sc
->callsc
&& sc
->callsc
->func
)
6712 fd
= sc
->callsc
->func
;
6719 const char *funcStr
= fd
->Dsymbol::toPrettyChars();
6721 functionToBufferWithIdent((TypeFunction
*)fd
->type
, &buf
, funcStr
);
6722 s
= buf
.extractString();
6729 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6730 e
= semantic(e
, sc
);
6731 e
= e
->castTo(sc
, type
);
6735 /****************************************************************/
6737 Expression
*extractOpDollarSideEffect(Scope
*sc
, UnaExp
*ue
)
6740 Expression
*e1
= Expression::extractLast(ue
->e1
, &e0
);
6741 // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
6743 if (!isTrivialExp(e1
))
6745 /* Even if opDollar is needed, 'e1' should be evaluate only once. So
6747 * e1.opIndex( ... use of $ ... )
6748 * e1.opSlice( ... use of $ ... )
6750 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
6751 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
6753 e1
= extractSideEffect(sc
, "__dop", &e0
, e1
, false);
6754 assert(e1
->op
== TOKvar
);
6755 VarExp
*ve
= (VarExp
*)e1
;
6756 ve
->var
->storage_class
|= STCexptemp
; // lifetime limited to expression
6762 /**************************************
6763 * Runs semantic on ae->arguments. Declares temporary variables
6766 Expression
*resolveOpDollar(Scope
*sc
, ArrayExp
*ae
, Expression
**pe0
)
6768 assert(!ae
->lengthVar
);
6772 AggregateDeclaration
*ad
= isAggregate(ae
->e1
->type
);
6773 Dsymbol
*slice
= search_function(ad
, Id::slice
);
6774 //printf("slice = %s %s\n", slice->kind(), slice->toChars());
6776 for (size_t i
= 0; i
< ae
->arguments
->dim
; i
++)
6779 *pe0
= extractOpDollarSideEffect(sc
, ae
);
6781 Expression
*e
= (*ae
->arguments
)[i
];
6782 if (e
->op
== TOKinterval
&& !(slice
&& slice
->isTemplateDeclaration()))
6785 if (ae
->arguments
->dim
== 1)
6787 ae
->error("multi-dimensional slicing requires template opSlice");
6788 return new ErrorExp();
6790 //printf("[%d] e = %s\n", i, e->toChars());
6792 // Create scope for '$' variable for this dimension
6793 ArrayScopeSymbol
*sym
= new ArrayScopeSymbol(sc
, ae
);
6795 sym
->parent
= sc
->scopesym
;
6797 ae
->lengthVar
= NULL
; // Create it only if required
6798 ae
->currentDimension
= i
; // Dimension for $, if required
6800 e
= semantic(e
, sc
);
6801 e
= resolveProperties(sc
, e
);
6803 if (ae
->lengthVar
&& sc
->func
)
6805 // If $ was used, declare it now
6806 Expression
*de
= new DeclarationExp(ae
->loc
, ae
->lengthVar
);
6807 de
= semantic(de
, sc
);
6808 *pe0
= Expression::combine(*pe0
, de
);
6812 if (e
->op
== TOKinterval
)
6814 IntervalExp
*ie
= (IntervalExp
*)e
;
6816 Objects
*tiargs
= new Objects();
6817 Expression
*edim
= new IntegerExp(ae
->loc
, i
, Type::tsize_t
);
6818 edim
= semantic(edim
, sc
);
6821 Expressions
*fargs
= new Expressions();
6822 fargs
->push(ie
->lwr
);
6823 fargs
->push(ie
->upr
);
6825 unsigned xerrors
= global
.startGagging();
6827 FuncDeclaration
*fslice
= resolveFuncCall(ae
->loc
, sc
, slice
, tiargs
, ae
->e1
->type
, fargs
, 1);
6829 global
.endGagging(xerrors
);
6833 e
= new DotTemplateInstanceExp(ae
->loc
, ae
->e1
, slice
->ident
, tiargs
);
6834 e
= new CallExp(ae
->loc
, e
, fargs
);
6835 e
= semantic(e
, sc
);
6840 ae
->error("%s has no value", e
->toChars());
6843 if (e
->op
== TOKerror
)
6846 (*ae
->arguments
)[i
] = e
;
6852 /**************************************
6853 * Runs semantic on se->lwr and se->upr. Declares a temporary variable
6856 Expression
*resolveOpDollar(Scope
*sc
, ArrayExp
*ae
, IntervalExp
*ie
, Expression
**pe0
)
6858 //assert(!ae->lengthVar);
6862 VarDeclaration
*lengthVar
= ae
->lengthVar
;
6864 // create scope for '$'
6865 ArrayScopeSymbol
*sym
= new ArrayScopeSymbol(sc
, ae
);
6867 sym
->parent
= sc
->scopesym
;
6870 for (size_t i
= 0; i
< 2; ++i
)
6872 Expression
*e
= i
== 0 ? ie
->lwr
: ie
->upr
;
6873 e
= semantic(e
, sc
);
6874 e
= resolveProperties(sc
, e
);
6877 ae
->error("%s has no value", e
->toChars());
6878 return new ErrorExp();
6880 (i
== 0 ? ie
->lwr
: ie
->upr
) = e
;
6883 if (lengthVar
!= ae
->lengthVar
&& sc
->func
)
6885 // If $ was used, declare it now
6886 Expression
*de
= new DeclarationExp(ae
->loc
, ae
->lengthVar
);
6887 de
= semantic(de
, sc
);
6888 *pe0
= Expression::combine(*pe0
, de
);
6895 Expression
*BinExp::reorderSettingAAElem(Scope
*sc
)
6899 if (be
->e1
->op
!= TOKindex
)
6901 IndexExp
*ie
= (IndexExp
*)be
->e1
;
6902 if (ie
->e1
->type
->toBasetype()->ty
!= Taarray
)
6905 /* Fix evaluation order of setting AA element. (Bugzilla 3825)
6907 * aa[k1][k2][k3] op= val;
6909 * auto ref __aatmp = aa;
6910 * auto ref __aakey3 = k1, __aakey2 = k2, __aakey1 = k3;
6911 * auto ref __aaval = val;
6912 * __aatmp[__aakey3][__aakey2][__aakey1] op= __aaval; // assignment
6915 Expression
*e0
= NULL
;
6918 Expression
*de
= NULL
;
6919 ie
->e2
= extractSideEffect(sc
, "__aakey", &de
, ie
->e2
);
6920 e0
= Expression::combine(de
, e0
);
6922 Expression
*ie1
= ie
->e1
;
6923 if (ie1
->op
!= TOKindex
||
6924 ((IndexExp
*)ie1
)->e1
->type
->toBasetype()->ty
!= Taarray
)
6928 ie
= (IndexExp
*)ie1
;
6930 assert(ie
->e1
->type
->toBasetype()->ty
== Taarray
);
6932 Expression
*de
= NULL
;
6933 ie
->e1
= extractSideEffect(sc
, "__aatmp", &de
, ie
->e1
);
6934 e0
= Expression::combine(de
, e0
);
6936 be
->e2
= extractSideEffect(sc
, "__aaval", &e0
, be
->e2
, true);
6938 //printf("-e0 = %s, be = %s\n", e0->toChars(), be->toChars());
6939 return Expression::combine(e0
, be
);