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
17 #include "root/rmem.h"
18 #include "root/root.h"
23 #include "expression.h"
28 #include "statement.h"
29 #include "declaration.h"
30 #include "aggregate.h"
44 bool walkPostorder(Expression
*e
, StoppableVisitor
*v
);
45 bool checkParamArgumentEscape(Scope
*sc
, FuncDeclaration
*fdc
, Identifier
*par
, Expression
*arg
, bool gag
);
46 bool checkAccess(AggregateDeclaration
*ad
, Loc loc
, Scope
*sc
, Dsymbol
*smember
);
47 VarDeclaration
*copyToTemp(StorageClass stc
, const char *name
, Expression
*e
);
48 Expression
*extractSideEffect(Scope
*sc
, const char *name
, Expression
**e0
, Expression
*e
, bool alwaysCopy
= false);
49 char *MODtoChars(MOD mod
);
50 bool MODimplicitConv(MOD modfrom
, MOD modto
);
51 MOD
MODmerge(MOD mod1
, MOD mod2
);
52 void MODMatchToBuffer(OutBuffer
*buf
, unsigned char lhsMod
, unsigned char rhsMod
);
53 Expression
*trySemantic(Expression
*e
, Scope
*sc
);
54 Expression
*semantic(Expression
*e
, Scope
*sc
);
55 Expression
*semanticX(DotIdExp
*exp
, Scope
*sc
);
56 Expression
*semanticY(DotIdExp
*exp
, Scope
*sc
, int flag
);
57 Expression
*semanticY(DotTemplateInstanceExp
*exp
, Scope
*sc
, int flag
);
58 Expression
*resolve(Loc loc
, Scope
*sc
, Dsymbol
*s
, bool hasOverloads
);
59 bool checkUnsafeAccess(Scope
*sc
, Expression
*e
, bool readonly
, bool printmsg
);
61 /*************************************************************
62 * Given var, we need to get the
63 * right 'this' pointer if var is in an outer class, but our
64 * existing 'this' pointer is in an inner class.
67 * ad struct or class we need the correct 'this' for
68 * var the specific member of ad we're accessing
71 Expression
*getRightThis(Loc loc
, Scope
*sc
, AggregateDeclaration
*ad
,
72 Expression
*e1
, Declaration
*var
, int flag
= 0)
74 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
76 Type
*t
= e1
->type
->toBasetype();
77 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
79 /* If e1 is not the 'this' pointer for ad
82 !(t
->ty
== Tpointer
&& t
->nextOf()->ty
== Tstruct
&&
83 ((TypeStruct
*)t
->nextOf())->sym
== ad
)
86 ((TypeStruct
*)t
)->sym
== ad
)
89 ClassDeclaration
*cd
= ad
->isClassDeclaration();
90 ClassDeclaration
*tcd
= t
->isClassHandle();
92 /* e1 is the right this if ad is a base class of e1
95 !(tcd
== cd
|| cd
->isBaseOf(tcd
, NULL
))
98 /* Only classes can be inner classes with an 'outer'
99 * member pointing to the enclosing class instance
101 if (tcd
&& tcd
->isNested())
103 /* e1 is the 'this' pointer for an inner class: tcd.
104 * Rewrite it as the 'this' pointer for the outer class.
107 e1
= new DotVarExp(loc
, e1
, tcd
->vthis
);
108 e1
->type
= tcd
->vthis
->type
;
109 e1
->type
= e1
->type
->addMod(t
->mod
);
110 // Do not call checkNestedRef()
111 //e1 = semantic(e1, sc);
113 // Skip up over nested functions, and get the enclosing
117 for (s
= tcd
->toParent();
118 s
&& s
->isFuncDeclaration();
121 FuncDeclaration
*f
= s
->isFuncDeclaration();
124 //printf("rewriting e1 to %s's this\n", f->toChars());
126 e1
= new VarExp(loc
, f
->vthis
);
130 e1
->error("need 'this' of type %s to access member %s"
131 " from static function %s",
132 ad
->toChars(), var
->toChars(), f
->toChars());
137 if (s
&& s
->isClassDeclaration())
139 e1
->type
= s
->isClassDeclaration()->type
;
140 e1
->type
= e1
->type
->addMod(t
->mod
);
142 e1
= semantic(e1
, sc
);
145 e1
= semantic(e1
, sc
);
149 /* Can't find a path from e1 to ad
153 e1
->error("this for %s needs to be type %s not type %s",
154 var
->toChars(), ad
->toChars(), t
->toChars());
155 return new ErrorExp();
161 /*****************************************
162 * Determine if 'this' is available.
163 * If it is, return the FuncDeclaration that has it.
166 FuncDeclaration
*hasThis(Scope
*sc
)
168 //printf("hasThis()\n");
169 Dsymbol
*p
= sc
->parent
;
170 while (p
&& p
->isTemplateMixin())
172 FuncDeclaration
*fdthis
= p
? p
->isFuncDeclaration() : NULL
;
173 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
175 // Go upwards until we find the enclosing member function
176 FuncDeclaration
*fd
= fdthis
;
186 Dsymbol
*parent
= fd
->parent
;
191 TemplateInstance
*ti
= parent
->isTemplateInstance();
197 fd
= parent
->isFuncDeclaration();
201 { //printf("test '%s'\n", fd->toChars());
209 return NULL
; // don't have 'this' available
212 bool isNeedThisScope(Scope
*sc
, Declaration
*d
)
214 if (sc
->intypeof
== 1)
217 AggregateDeclaration
*ad
= d
->isThis();
220 //printf("d = %s, ad = %s\n", d->toChars(), ad->toChars());
222 for (Dsymbol
*s
= sc
->parent
; s
; s
= s
->toParent2())
224 //printf("\ts = %s %s, toParent2() = %p\n", s->kind(), s->toChars(), s->toParent2());
225 if (AggregateDeclaration
*ad2
= s
->isAggregateDeclaration())
229 else if (ad2
->isNested())
234 if (FuncDeclaration
*f
= s
->isFuncDeclaration())
243 /***************************************
244 * Pull out any properties.
247 Expression
*resolvePropertiesX(Scope
*sc
, Expression
*e1
, Expression
*e2
= NULL
)
249 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
256 if (e1
->op
== TOKdot
)
258 DotExp
*de
= (DotExp
*)e1
;
259 if (de
->e2
->op
== TOKoverloadset
)
262 tthis
= de
->e1
->type
;
263 os
= ((OverExp
*)de
->e2
)->vars
;
267 else if (e1
->op
== TOKoverloadset
)
271 os
= ((OverExp
*)e1
)->vars
;
274 FuncDeclaration
*fd
= NULL
;
277 e2
= semantic(e2
, sc
);
278 if (e2
->op
== TOKerror
)
279 return new ErrorExp();
280 e2
= resolveProperties(sc
, e2
);
285 for (size_t i
= 0; i
< os
->a
.dim
; i
++)
287 FuncDeclaration
*f
= resolveFuncCall(loc
, sc
, os
->a
[i
], tiargs
, tthis
, &a
, 1);
291 return new ErrorExp();
293 assert(fd
->type
->ty
== Tfunction
);
298 Expression
*e
= new CallExp(loc
, e1
, e2
);
299 return semantic(e
, sc
);
303 for (size_t i
= 0; i
< os
->a
.dim
; i
++)
305 FuncDeclaration
*f
= resolveFuncCall(loc
, sc
, os
->a
[i
], tiargs
, tthis
, NULL
, 1);
309 return new ErrorExp();
311 assert(fd
->type
->ty
== Tfunction
);
312 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
313 if (!tf
->isref
&& e2
)
319 Expression
*e
= new CallExp(loc
, e1
);
321 e
= new AssignExp(loc
, e
, e2
);
322 return semantic(e
, sc
);
328 else if (e1
->op
== TOKdotti
)
330 DotTemplateInstanceExp
* dti
= (DotTemplateInstanceExp
*)e1
;
331 if (!dti
->findTempDecl(sc
))
333 if (!dti
->ti
->semanticTiargs(sc
))
335 tiargs
= dti
->ti
->tiargs
;
336 tthis
= dti
->e1
->type
;
337 if ((os
= dti
->ti
->tempdecl
->isOverloadSet()) != NULL
)
339 if ((s
= dti
->ti
->tempdecl
) != NULL
)
342 else if (e1
->op
== TOKdottd
)
344 DotTemplateExp
*dte
= (DotTemplateExp
*)e1
;
347 tthis
= dte
->e1
->type
;
350 else if (e1
->op
== TOKscope
)
352 s
= ((ScopeExp
*)e1
)->sds
;
353 TemplateInstance
*ti
= s
->isTemplateInstance();
354 if (ti
&& !ti
->semanticRun
&& ti
->tempdecl
)
356 //assert(ti->needsTypeInference(sc));
357 if (!ti
->semanticTiargs(sc
))
361 if ((os
= ti
->tempdecl
->isOverloadSet()) != NULL
)
363 if ((s
= ti
->tempdecl
) != NULL
)
367 else if (e1
->op
== TOKtemplate
)
369 s
= ((TemplateExp
*)e1
)->td
;
374 else if (e1
->op
== TOKdotvar
&& e1
->type
&& e1
->type
->toBasetype()->ty
== Tfunction
)
376 DotVarExp
*dve
= (DotVarExp
*)e1
;
377 s
= dve
->var
->isFuncDeclaration();
379 tthis
= dve
->e1
->type
;
382 else if (e1
->op
== TOKvar
&& e1
->type
&& e1
->type
->toBasetype()->ty
== Tfunction
)
384 s
= ((VarExp
*)e1
)->var
->isFuncDeclaration();
391 e2
= semantic(e2
, sc
);
392 if (e2
->op
== TOKerror
)
393 return new ErrorExp();
394 e2
= resolveProperties(sc
, e2
);
399 FuncDeclaration
*fd
= resolveFuncCall(loc
, sc
, s
, tiargs
, tthis
, &a
, 1);
403 return new ErrorExp();
404 assert(fd
->type
->ty
== Tfunction
);
405 Expression
*e
= new CallExp(loc
, e1
, e2
);
406 return semantic(e
, sc
);
410 FuncDeclaration
*fd
= resolveFuncCall(loc
, sc
, s
, tiargs
, tthis
, NULL
, 1);
414 return new ErrorExp();
415 assert(fd
->type
->ty
== Tfunction
);
416 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
417 if (!e2
|| tf
->isref
)
419 Expression
*e
= new CallExp(loc
, e1
);
421 e
= new AssignExp(loc
, e
, e2
);
422 return semantic(e
, sc
);
426 if (FuncDeclaration
*fd
= s
->isFuncDeclaration())
428 // Keep better diagnostic message for invalid property usage of functions
429 assert(fd
->type
->ty
== Tfunction
);
430 Expression
*e
= new CallExp(loc
, e1
, e2
);
431 return semantic(e
, sc
);
436 if (e1
->op
== TOKvar
)
438 VarExp
*ve
= (VarExp
*)e1
;
439 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
440 if (v
&& ve
->checkPurity(sc
, v
))
441 return new ErrorExp();
447 e1
->op
!= TOKtype
) // function type is not a property
449 /* Look for e1 being a lazy parameter; rewrite as delegate call
451 if (e1
->op
== TOKvar
)
453 VarExp
*ve
= (VarExp
*)e1
;
455 if (ve
->var
->storage_class
& STClazy
)
457 Expression
*e
= new CallExp(loc
, e1
);
458 return semantic(e
, sc
);
461 else if (e1
->op
== TOKdotvar
)
463 // Check for reading overlapped pointer field in @safe code.
464 if (checkUnsafeAccess(sc
, e1
, true, true))
465 return new ErrorExp();
467 else if (e1
->op
== TOKdot
)
469 e1
->error("expression has no value");
470 return new ErrorExp();
472 else if (e1
->op
== TOKcall
)
474 CallExp
*ce
= (CallExp
*)e1
;
475 // Check for reading overlapped pointer field in @safe code.
476 if (checkUnsafeAccess(sc
, ce
->e1
, true, true))
477 return new ErrorExp();
483 error(loc
, "cannot resolve type for %s", e1
->toChars());
489 error(loc
, "not a property %s", e1
->toChars());
490 return new ErrorExp();
493 error(loc
, "%s is not an lvalue", e1
->toChars());
494 return new ErrorExp();
497 Expression
*resolveProperties(Scope
*sc
, Expression
*e
)
499 //printf("resolveProperties(%s)\n", e->toChars());
501 e
= resolvePropertiesX(sc
, e
);
502 if (e
->checkRightThis(sc
))
503 return new ErrorExp();
507 /******************************
508 * Check the tail CallExp is really property function call.
510 static bool checkPropertyCall(Expression
*e
)
512 while (e
->op
== TOKcomma
)
513 e
= ((CommaExp
*)e
)->e2
;
515 if (e
->op
== TOKcall
)
517 CallExp
*ce
= (CallExp
*)e
;
521 tf
= (TypeFunction
*)ce
->f
->type
;
522 /* If a forward reference to ce->f, try to resolve it
524 if (!tf
->deco
&& ce
->f
->_scope
)
526 ce
->f
->semantic(ce
->f
->_scope
);
527 tf
= (TypeFunction
*)ce
->f
->type
;
530 else if (ce
->e1
->type
->ty
== Tfunction
)
531 tf
= (TypeFunction
*)ce
->e1
->type
;
532 else if (ce
->e1
->type
->ty
== Tdelegate
)
533 tf
= (TypeFunction
*)ce
->e1
->type
->nextOf();
534 else if (ce
->e1
->type
->ty
== Tpointer
&& ce
->e1
->type
->nextOf()->ty
== Tfunction
)
535 tf
= (TypeFunction
*)ce
->e1
->type
->nextOf();
542 /******************************
543 * If e1 is a property function (template), resolve it.
546 Expression
*resolvePropertiesOnly(Scope
*sc
, Expression
*e1
)
548 //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
551 TemplateDeclaration
*td
;
553 if (e1
->op
== TOKdot
)
555 DotExp
*de
= (DotExp
*)e1
;
556 if (de
->e2
->op
== TOKoverloadset
)
558 os
= ((OverExp
*)de
->e2
)->vars
;
562 else if (e1
->op
== TOKoverloadset
)
564 os
= ((OverExp
*)e1
)->vars
;
567 for (size_t i
= 0; i
< os
->a
.dim
; i
++)
569 Dsymbol
*s
= os
->a
[i
];
570 fd
= s
->isFuncDeclaration();
571 td
= s
->isTemplateDeclaration();
574 if (((TypeFunction
*)fd
->type
)->isproperty
)
575 return resolveProperties(sc
, e1
);
577 else if (td
&& td
->onemember
&&
578 (fd
= td
->onemember
->isFuncDeclaration()) != NULL
)
580 if (((TypeFunction
*)fd
->type
)->isproperty
||
581 (fd
->storage_class2
& STCproperty
) ||
582 (td
->_scope
->stc
& STCproperty
))
584 return resolveProperties(sc
, e1
);
589 else if (e1
->op
== TOKdotti
)
591 DotTemplateInstanceExp
* dti
= (DotTemplateInstanceExp
*)e1
;
592 if (dti
->ti
->tempdecl
&& (td
= dti
->ti
->tempdecl
->isTemplateDeclaration()) != NULL
)
595 else if (e1
->op
== TOKdottd
)
597 td
= ((DotTemplateExp
*)e1
)->td
;
600 else if (e1
->op
== TOKscope
)
602 Dsymbol
*s
= ((ScopeExp
*)e1
)->sds
;
603 TemplateInstance
*ti
= s
->isTemplateInstance();
604 if (ti
&& !ti
->semanticRun
&& ti
->tempdecl
)
606 if ((td
= ti
->tempdecl
->isTemplateDeclaration()) != NULL
)
610 else if (e1
->op
== TOKtemplate
)
612 td
= ((TemplateExp
*)e1
)->td
;
616 (fd
= td
->onemember
->isFuncDeclaration()) != NULL
)
618 if (((TypeFunction
*)fd
->type
)->isproperty
||
619 (fd
->storage_class2
& STCproperty
) ||
620 (td
->_scope
->stc
& STCproperty
))
622 return resolveProperties(sc
, e1
);
626 else if (e1
->op
== TOKdotvar
&& e1
->type
->ty
== Tfunction
)
628 DotVarExp
*dve
= (DotVarExp
*)e1
;
629 fd
= dve
->var
->isFuncDeclaration();
632 else if (e1
->op
== TOKvar
&& e1
->type
->ty
== Tfunction
&&
633 (sc
->intypeof
|| !((VarExp
*)e1
)->var
->needThis()))
635 fd
= ((VarExp
*)e1
)->var
->isFuncDeclaration();
638 if (((TypeFunction
*)fd
->type
)->isproperty
)
639 return resolveProperties(sc
, e1
);
645 // TODO: merge with Scope::search::searchScopes()
646 static Dsymbol
*searchScopes(Scope
*sc
, Loc loc
, Identifier
*ident
, int flags
)
649 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
653 if (scx
->scopesym
->isModule())
654 flags
|= SearchUnqualifiedModule
; // tell Module.search() that SearchLocalsOnly is to be obeyed
655 s
= scx
->scopesym
->search(loc
, ident
, flags
);
658 // overload set contains only module scope symbols.
659 if (s
->isOverloadSet())
661 // selective/renamed imports also be picked up
662 if (AliasDeclaration
*ad
= s
->isAliasDeclaration())
667 // See only module scope symbols for UFCS target.
668 Dsymbol
*p
= s
->toParent2();
669 if (p
&& p
->isModule())
674 // Stop when we hit a module, but keep going if that is not just under the global scope
675 if (scx
->scopesym
->isModule() && !(scx
->enclosing
&& !scx
->enclosing
->enclosing
))
681 /******************************
682 * Find symbol in accordance with the UFCS name look up rule
685 Expression
*searchUFCS(Scope
*sc
, UnaExp
*ue
, Identifier
*ident
)
687 //printf("searchUFCS(ident = %s)\n", ident->toChars());
692 if (sc
->flags
& SCOPEignoresymbolvisibility
)
693 flags
|= IgnoreSymbolVisibility
;
695 Dsymbol
*sold
= NULL
;
696 if (global
.params
.bug10378
|| global
.params
.check10378
)
698 sold
= searchScopes(sc
, loc
, ident
, flags
| IgnoreSymbolVisibility
);
699 if (!global
.params
.check10378
)
706 // First look in local scopes
707 s
= searchScopes(sc
, loc
, ident
, flags
| SearchLocalsOnly
);
710 // Second look in imported modules
711 s
= searchScopes(sc
, loc
, ident
, flags
| SearchImportsOnly
);
713 /** Still find private symbols, so that symbols that weren't access
714 * checked by the compiler remain usable. Once the deprecation is over,
715 * this should be moved to search_correct instead.
717 if (!s
&& !(flags
& IgnoreSymbolVisibility
))
719 s
= searchScopes(sc
, loc
, ident
, flags
| SearchLocalsOnly
| IgnoreSymbolVisibility
);
721 s
= searchScopes(sc
, loc
, ident
, flags
| SearchImportsOnly
| IgnoreSymbolVisibility
);
723 ::deprecation(loc
, "%s is not visible from module %s", s
->toPrettyChars(), sc
->_module
->toChars());
726 if (global
.params
.check10378
)
730 Scope::deprecation10378(loc
, sold
, snew
);
731 if (global
.params
.bug10378
)
737 return ue
->e1
->type
->Type::getProperty(loc
, ident
, 0);
739 FuncDeclaration
*f
= s
->isFuncDeclaration();
742 TemplateDeclaration
*td
= getFuncTemplateDecl(f
);
751 if (ue
->op
== TOKdotti
)
753 DotTemplateInstanceExp
*dti
= (DotTemplateInstanceExp
*)ue
;
754 TemplateInstance
*ti
= new TemplateInstance(loc
, s
->ident
);
755 ti
->tiargs
= dti
->ti
->tiargs
; // for better diagnostic message
756 if (!ti
->updateTempDecl(sc
, s
))
757 return new ErrorExp();
758 return new ScopeExp(loc
, ti
);
762 //printf("-searchUFCS() %s\n", s->toChars());
763 return new DsymbolExp(loc
, s
);
767 /******************************
768 * check e is exp.opDispatch!(tiargs) or not
769 * It's used to switch to UFCS the semantic analysis path
772 bool isDotOpDispatch(Expression
*e
)
774 return e
->op
== TOKdotti
&&
775 ((DotTemplateInstanceExp
*)e
)->ti
->name
== Id::opDispatch
;
778 /******************************
779 * Pull out callable entity with UFCS.
782 Expression
*resolveUFCS(Scope
*sc
, CallExp
*ce
)
788 if (ce
->e1
->op
== TOKdotid
)
790 DotIdExp
*die
= (DotIdExp
*)ce
->e1
;
791 Identifier
*ident
= die
->ident
;
793 Expression
*ex
= semanticX(die
, sc
);
801 Type
*t
= eleft
->type
->toBasetype();
802 if (t
->ty
== Tarray
|| t
->ty
== Tsarray
||
803 t
->ty
== Tnull
|| (t
->isTypeBasic() && t
->ty
!= Tvoid
))
805 /* Built-in types and arrays have no callable properties, so do shortcut.
806 * It is necessary in: e.init()
809 else if (t
->ty
== Taarray
)
811 if (ident
== Id::remove
)
814 * aa.remove(arg) into delete aa[arg]
816 if (!ce
->arguments
|| ce
->arguments
->dim
!= 1)
818 ce
->error("expected key as argument to aa.remove()");
819 return new ErrorExp();
821 if (!eleft
->type
->isMutable())
823 ce
->error("cannot remove key from %s associative array %s",
824 MODtoChars(t
->mod
), eleft
->toChars());
825 return new ErrorExp();
827 Expression
*key
= (*ce
->arguments
)[0];
828 key
= semantic(key
, sc
);
829 key
= resolveProperties(sc
, key
);
831 TypeAArray
*taa
= (TypeAArray
*)t
;
832 key
= key
->implicitCastTo(sc
, taa
->index
);
834 if (key
->checkValue())
835 return new ErrorExp();
837 semanticTypeInfo(sc
, taa
->index
);
839 return new RemoveExp(loc
, eleft
, key
);
844 if (Expression
*ey
= semanticY(die
, sc
, 1))
846 if (ey
->op
== TOKerror
)
849 if (isDotOpDispatch(ey
))
851 unsigned errors
= global
.startGagging();
852 e
= semantic(ce
->syntaxCopy(), sc
);
853 if (!global
.endGagging(errors
))
855 /* fall down to UFCS */
861 e
= searchUFCS(sc
, die
, ident
);
863 else if (ce
->e1
->op
== TOKdotti
)
865 DotTemplateInstanceExp
*dti
= (DotTemplateInstanceExp
*)ce
->e1
;
866 if (Expression
*ey
= semanticY(dti
, sc
, 1))
872 e
= searchUFCS(sc
, dti
, dti
->ti
->name
);
880 ce
->arguments
= new Expressions();
881 ce
->arguments
->shift(eleft
);
886 /******************************
887 * Pull out property with UFCS.
890 Expression
*resolveUFCSProperties(Scope
*sc
, Expression
*e1
, Expression
*e2
= NULL
)
896 if (e1
->op
== TOKdotid
)
898 DotIdExp
*die
= (DotIdExp
*)e1
;
900 e
= searchUFCS(sc
, die
, die
->ident
);
902 else if (e1
->op
== TOKdotti
)
904 DotTemplateInstanceExp
*dti
;
905 dti
= (DotTemplateInstanceExp
*)e1
;
907 e
= searchUFCS(sc
, dti
, dti
->ti
->name
);
918 // run semantic without gagging
919 e2
= semantic(e2
, sc
);
923 Expression
*ex
= e
->copy();
924 Expressions
*a1
= new Expressions();
927 ex
= new CallExp(loc
, ex
, a1
);
928 ex
= trySemantic(ex
, sc
);
932 Expressions
*a2
= new Expressions();
936 e
= new CallExp(loc
, e
, a2
);
938 { // if fallback setter exists, gag errors
939 e
= trySemantic(e
, sc
);
941 { checkPropertyCall(ex
);
942 ex
= new AssignExp(loc
, ex
, e2
);
943 return semantic(ex
, sc
);
947 { // strict setter prints errors if fails
950 checkPropertyCall(e
);
957 Expressions
*arguments
= new Expressions();
958 arguments
->setDim(1);
959 (*arguments
)[0] = eleft
;
960 e
= new CallExp(loc
, e
, arguments
);
962 checkPropertyCall(e
);
963 return semantic(e
, sc
);
967 /******************************
968 * Perform semantic() on an array of Expressions.
971 bool arrayExpressionSemantic(Expressions
*exps
, Scope
*sc
, bool preserveErrors
)
976 for (size_t i
= 0; i
< exps
->dim
; i
++)
978 Expression
*e
= (*exps
)[i
];
982 if (e
->op
== TOKerror
)
984 if (preserveErrors
|| e
->op
!= TOKerror
)
992 /****************************************
995 * exps aray of Expressions
997 * exps rewritten in place
1000 void expandTuples(Expressions
*exps
)
1002 //printf("expandTuples()\n");
1005 for (size_t i
= 0; i
< exps
->dim
; i
++)
1007 Expression
*arg
= (*exps
)[i
];
1011 // Look for tuple with 0 members
1012 if (arg
->op
== TOKtype
)
1014 TypeExp
*e
= (TypeExp
*)arg
;
1015 if (e
->type
->toBasetype()->ty
== Ttuple
)
1017 TypeTuple
*tt
= (TypeTuple
*)e
->type
->toBasetype();
1019 if (!tt
->arguments
|| tt
->arguments
->dim
== 0)
1030 // Inline expand all the tuples
1031 while (arg
->op
== TOKtuple
)
1033 TupleExp
*te
= (TupleExp
*)arg
;
1034 exps
->remove(i
); // remove arg
1035 exps
->insert(i
, te
->exps
); // replace with tuple contents
1037 return; // empty tuple, no more arguments
1038 (*exps
)[i
] = Expression::combine(te
->e0
, (*exps
)[i
]);
1045 /****************************************
1046 * Expand alias this tuples.
1049 TupleDeclaration
*isAliasThisTuple(Expression
*e
)
1054 Type
*t
= e
->type
->toBasetype();
1056 if (Dsymbol
*s
= t
->toDsymbol(NULL
))
1058 AggregateDeclaration
*ad
= s
->isAggregateDeclaration();
1062 if (s
&& s
->isVarDeclaration())
1064 TupleDeclaration
*td
= s
->isVarDeclaration()->toAlias()->isTupleDeclaration();
1065 if (td
&& td
->isexp
)
1068 if (Type
*att
= t
->aliasthisOf())
1078 int expandAliasThisTuples(Expressions
*exps
, size_t starti
)
1080 if (!exps
|| exps
->dim
== 0)
1083 for (size_t u
= starti
; u
< exps
->dim
; u
++)
1085 Expression
*exp
= (*exps
)[u
];
1086 TupleDeclaration
*td
= isAliasThisTuple(exp
);
1090 for (size_t i
= 0; i
<td
->objects
->dim
; ++i
)
1092 Expression
*e
= isExpression((*td
->objects
)[i
]);
1094 assert(e
->op
== TOKdsymbol
);
1095 DsymbolExp
*se
= (DsymbolExp
*)e
;
1096 Declaration
*d
= se
->s
->isDeclaration();
1098 e
= new DotVarExp(exp
->loc
, exp
, d
);
1101 exps
->insert(u
+ i
, e
);
1110 /****************************************
1111 * The common type is determined by applying ?: to each pair.
1113 * exps[] properties resolved, implicitly cast to common type, rewritten in place
1114 * *pt if pt is not NULL, set to the common type
1116 * true a semantic error was detected
1119 bool arrayExpressionToCommonType(Scope
*sc
, Expressions
*exps
, Type
**pt
)
1121 /* Still have a problem with:
1122 * ubyte[][] = [ cast(ubyte[])"hello", [1]];
1123 * which works if the array literal is initialized top down with the ubyte[][]
1124 * type, but fails with this function doing bottom up typing.
1126 //printf("arrayExpressionToCommonType()\n");
1127 IntegerExp
integerexp(0);
1128 CondExp
condexp(Loc(), &integerexp
, NULL
, NULL
);
1131 Expression
*e0
= NULL
; // dead-store to prevent spurious warning
1132 size_t j0
= ~0; // dead-store to prevent spurious warning
1133 for (size_t i
= 0; i
< exps
->dim
; i
++)
1135 Expression
*e
= (*exps
)[i
];
1139 e
= resolveProperties(sc
, e
);
1142 e
->error("%s has no value", e
->toChars());
1146 if (e
->op
== TOKtype
)
1148 e
->checkValue(); // report an error "type T has no value"
1152 if (e
->type
->ty
== Tvoid
)
1154 // void expressions do not concur to the determination of the common
1158 if (checkNonAssignmentArrayOp(e
))
1164 e
= doCopyOrMove(sc
, e
);
1166 if (t0
&& !t0
->equals(e
->type
))
1168 /* This applies ?: to merge the types. It's backwards;
1169 * ?: should call this function to merge types.
1171 condexp
.type
= NULL
;
1174 condexp
.loc
= e
->loc
;
1175 Expression
*ex
= semantic(&condexp
, sc
);
1176 if (ex
->op
== TOKerror
)
1180 (*exps
)[j0
] = condexp
.e1
;
1187 if (e
->op
!= TOKerror
)
1192 t0
= Type::tvoid
; // [] is typed as void[]
1193 else if (t0
->ty
!= Terror
)
1195 for (size_t i
= 0; i
< exps
->dim
; i
++)
1197 Expression
*e
= (*exps
)[i
];
1201 e
= e
->implicitCastTo(sc
, t0
);
1202 //assert(e->op != TOKerror);
1203 if (e
->op
== TOKerror
)
1205 /* Bugzilla 13024: a workaround for the bug in typeMerge -
1206 * it should paint e1 and e2 by deduced common type,
1207 * but doesn't in this particular case.
1218 return (t0
== Type::terror
);
1221 /****************************************
1222 * Get TemplateDeclaration enclosing FuncDeclaration.
1225 TemplateDeclaration
*getFuncTemplateDecl(Dsymbol
*s
)
1227 FuncDeclaration
*f
= s
->isFuncDeclaration();
1230 TemplateInstance
*ti
= f
->parent
->isTemplateInstance();
1231 if (ti
&& !ti
->isTemplateMixin() &&
1232 ti
->tempdecl
&& ((TemplateDeclaration
*)ti
->tempdecl
)->onemember
&&
1233 ti
->tempdecl
->ident
== f
->ident
)
1235 return (TemplateDeclaration
*)ti
->tempdecl
;
1241 /************************************************
1242 * If we want the value of this expression, but do not want to call
1243 * the destructor on it.
1246 Expression
*valueNoDtor(Expression
*e
)
1248 if (e
->op
== TOKcall
)
1250 /* The struct value returned from the function is transferred
1251 * so do not call the destructor on it.
1253 * ((S _ctmp = S.init), _ctmp).this(...)
1254 * and make sure the destructor is not called on _ctmp
1255 * BUG: if e is a CommaExp, we should go down the right side.
1257 CallExp
*ce
= (CallExp
*)e
;
1258 if (ce
->e1
->op
== TOKdotvar
)
1260 DotVarExp
*dve
= (DotVarExp
*)ce
->e1
;
1261 if (dve
->var
->isCtorDeclaration())
1263 // It's a constructor call
1264 if (dve
->e1
->op
== TOKcomma
)
1266 CommaExp
*comma
= (CommaExp
*)dve
->e1
;
1267 if (comma
->e2
->op
== TOKvar
)
1269 VarExp
*ve
= (VarExp
*)comma
->e2
;
1270 VarDeclaration
*ctmp
= ve
->var
->isVarDeclaration();
1273 ctmp
->storage_class
|= STCnodtor
;
1274 assert(!ce
->isLvalue());
1281 else if (e
->op
== TOKvar
)
1283 VarDeclaration
*vtmp
= ((VarExp
*)e
)->var
->isVarDeclaration();
1284 if (vtmp
&& vtmp
->storage_class
& STCrvalue
)
1286 vtmp
->storage_class
|= STCnodtor
;
1292 /********************************************
1293 * Issue an error if default construction is disabled for type t.
1294 * Default construction is required for arrays and 'out' parameters.
1296 * true an error was issued
1298 bool checkDefCtor(Loc loc
, Type
*t
)
1300 t
= t
->baseElemOf();
1301 if (t
->ty
== Tstruct
)
1303 StructDeclaration
*sd
= ((TypeStruct
*)t
)->sym
;
1304 if (sd
->noDefaultCtor
)
1306 sd
->error(loc
, "default construction is disabled");
1313 /*********************************************
1314 * If e is an instance of a struct, and that struct has a copy constructor,
1318 * sc just used to specify the scope of created temporary variable
1320 Expression
*callCpCtor(Scope
*sc
, Expression
*e
)
1322 Type
*tv
= e
->type
->baseElemOf();
1323 if (tv
->ty
== Tstruct
)
1325 StructDeclaration
*sd
= ((TypeStruct
*)tv
)->sym
;
1328 /* Create a variable tmp, and replace the argument e with:
1330 * and let AssignExp() handle the construction.
1331 * This is not the most efficent, ideally tmp would be constructed
1332 * directly onto the stack.
1334 VarDeclaration
*tmp
= copyToTemp(STCrvalue
, "__copytmp", e
);
1335 tmp
->storage_class
|= STCnodtor
;
1337 Expression
*de
= new DeclarationExp(e
->loc
, tmp
);
1338 Expression
*ve
= new VarExp(e
->loc
, tmp
);
1339 de
->type
= Type::tvoid
;
1341 e
= Expression::combine(de
, ve
);
1347 /************************************************
1348 * Handle the postblit call on lvalue, or the move of rvalue.
1350 Expression
*doCopyOrMove(Scope
*sc
, Expression
*e
)
1352 if (e
->op
== TOKquestion
)
1354 CondExp
*ce
= (CondExp
*)e
;
1355 ce
->e1
= doCopyOrMove(sc
, ce
->e1
);
1356 ce
->e2
= doCopyOrMove(sc
, ce
->e2
);
1360 e
= e
->isLvalue() ? callCpCtor(sc
, e
) : valueNoDtor(e
);
1365 /****************************************
1366 * Now that we know the exact type of the function we're calling,
1367 * the arguments[] need to be adjusted:
1368 * 1. implicitly convert argument to the corresponding parameter type
1369 * 2. add default arguments for any missing arguments
1370 * 3. do default promotions on arguments corresponding to ...
1371 * 4. add hidden _arguments[] argument
1372 * 5. call copy constructor for struct value arguments
1374 * tf type of the function
1375 * fd the function being called, NULL if called indirectly
1377 * *prettype return type of function
1378 * *peprefix expression to execute before arguments[] are evaluated, NULL if none
1380 * true errors happened
1383 bool functionParameters(Loc loc
, Scope
*sc
, TypeFunction
*tf
,
1384 Type
*tthis
, Expressions
*arguments
, FuncDeclaration
*fd
, Type
**prettype
, Expression
**peprefix
)
1386 //printf("functionParameters()\n");
1388 assert(fd
|| tf
->next
);
1389 size_t nargs
= arguments
? arguments
->dim
: 0;
1390 size_t nparams
= Parameter::dim(tf
->parameters
);
1391 unsigned olderrors
= global
.errors
;
1393 *prettype
= Type::terror
;
1394 Expression
*eprefix
= NULL
;
1397 if (nargs
> nparams
&& tf
->varargs
== 0)
1399 error(loc
, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong
)nparams
, (ulonglong
)nargs
, tf
->toChars());
1403 // If inferring return type, and semantic3() needs to be run if not already run
1404 if (!tf
->next
&& fd
->inferRetType
)
1406 fd
->functionSemantic();
1408 else if (fd
&& fd
->parent
)
1410 TemplateInstance
*ti
= fd
->parent
->isTemplateInstance();
1411 if (ti
&& ti
->tempdecl
)
1413 fd
->functionSemantic3();
1416 bool isCtorCall
= fd
&& fd
->needThis() && fd
->isCtorDeclaration();
1418 size_t n
= (nargs
> nparams
) ? nargs
: nparams
; // n = max(nargs, nparams)
1420 /* If the function return type has wildcards in it, we'll need to figure out the actual type
1421 * based on the actual argument types.
1424 if (tthis
&& tf
->isWild() && !isCtorCall
)
1427 if (t
->isImmutable())
1428 wildmatch
= MODimmutable
;
1429 else if (t
->isWildConst())
1430 wildmatch
= MODwildconst
;
1431 else if (t
->isWild())
1432 wildmatch
= MODwild
;
1433 else if (t
->isConst())
1434 wildmatch
= MODconst
;
1436 wildmatch
= MODmutable
;
1440 for (size_t i
= 0; i
< n
; i
++)
1445 arg
= (*arguments
)[i
];
1451 Parameter
*p
= Parameter::getNth(tf
->parameters
, i
);
1457 if (tf
->varargs
== 2 && i
+ 1 == nparams
)
1459 error(loc
, "expected %llu function arguments, not %llu", (ulonglong
)nparams
, (ulonglong
)nargs
);
1462 arg
= p
->defaultArg
;
1463 arg
= inlineCopy(arg
, sc
);
1464 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1465 arg
= arg
->resolveLoc(loc
, sc
);
1466 arguments
->push(arg
);
1470 if (tf
->varargs
== 2 && i
+ 1 == nparams
)
1472 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
1475 if ((m
= arg
->implicitConvTo(p
->type
)) > MATCHnomatch
)
1477 if (p
->type
->nextOf() && arg
->implicitConvTo(p
->type
->nextOf()) >= m
)
1479 else if (nargs
!= nparams
)
1480 { error(loc
, "expected %llu function arguments, not %llu", (ulonglong
)nparams
, (ulonglong
)nargs
);
1487 Type
*tb
= p
->type
->toBasetype();
1488 Type
*tret
= p
->isLazyArray();
1494 /* Create a static array variable v of type arg->type:
1495 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1497 * The array literal in the initializer of the hidden variable
1498 * is now optimized. See Bugzilla 2356.
1500 Type
*tbn
= ((TypeArray
*)tb
)->next
;
1501 Type
*tsa
= tbn
->sarrayOf(nargs
- i
);
1503 Expressions
*elements
= new Expressions();
1504 elements
->setDim(nargs
- i
);
1505 for (size_t u
= 0; u
< elements
->dim
; u
++)
1507 Expression
*a
= (*arguments
)[i
+ u
];
1508 if (tret
&& a
->implicitConvTo(tret
))
1510 a
= a
->implicitCastTo(sc
, tret
);
1511 a
= a
->optimize(WANTvalue
);
1512 a
= toDelegate(a
, a
->type
, sc
);
1515 a
= a
->implicitCastTo(sc
, tbn
);
1518 // Bugzilla 14395: Convert to a static array literal, or its slice.
1519 arg
= new ArrayLiteralExp(loc
, elements
);
1521 if (tb
->ty
== Tarray
)
1523 arg
= new SliceExp(loc
, arg
, NULL
, NULL
);
1524 arg
->type
= p
->type
;
1531 * new Tclass(arg0, arg1, ..., argn)
1533 Expressions
*args
= new Expressions();
1534 args
->setDim(nargs
- i
);
1535 for (size_t u
= i
; u
< nargs
; u
++)
1536 (*args
)[u
- i
] = (*arguments
)[u
];
1537 arg
= new NewExp(loc
, NULL
, NULL
, p
->type
, args
);
1543 error(loc
, "not enough arguments");
1548 arg
= semantic(arg
, sc
);
1549 //printf("\targ = '%s'\n", arg->toChars());
1550 arguments
->setDim(i
+ 1);
1551 (*arguments
)[i
] = arg
;
1557 if (!(p
->storageClass
& STClazy
&& p
->type
->ty
== Tvoid
))
1559 bool isRef
= (p
->storageClass
& (STCref
| STCout
)) != 0;
1560 if (unsigned char wm
= arg
->type
->deduceWild(p
->type
, isRef
))
1563 wildmatch
= MODmerge(wildmatch
, wm
);
1566 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
1573 if ((wildmatch
== MODmutable
|| wildmatch
== MODimmutable
) &&
1574 tf
->next
->hasWild() &&
1575 (tf
->isref
|| !tf
->next
->implicitConvTo(tf
->next
->immutableOf())))
1579 /* If the called function may return the reference to
1580 * outer inout data, it should be rejected.
1582 * void foo(ref inout(int) x) {
1583 * ref inout(int) bar(inout(int)) { return x; }
1584 * struct S { ref inout(int) bar() inout { return x; } }
1585 * bar(int.init) = 1; // bad!
1586 * S().bar() = 1; // bad!
1590 if (fd
->isThis() || fd
->isNested())
1591 s
= fd
->toParent2();
1592 for (; s
; s
= s
->toParent2())
1594 if (AggregateDeclaration
*ad
= s
->isAggregateDeclaration())
1600 if (FuncDeclaration
*ff
= s
->isFuncDeclaration())
1602 if (((TypeFunction
*)ff
->type
)->iswild
)
1605 if (ff
->isNested() || ff
->isThis())
1611 else if (tf
->isWild())
1614 const char *s
= wildmatch
== MODmutable
? "mutable" : MODtoChars(wildmatch
);
1615 error(loc
, "modify inout to %s is not allowed inside inout function", s
);
1620 assert(nargs
>= nparams
);
1621 for (size_t i
= 0; i
< nargs
; i
++)
1623 Expression
*arg
= (*arguments
)[i
];
1627 Parameter
*p
= Parameter::getNth(tf
->parameters
, i
);
1629 if (!(p
->storageClass
& STClazy
&& p
->type
->ty
== Tvoid
))
1631 Type
*tprm
= p
->type
;
1632 if (p
->type
->hasWild())
1633 tprm
= p
->type
->substWildTo(wildmatch
);
1634 if (!tprm
->equals(arg
->type
))
1636 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
1637 arg
= arg
->implicitCastTo(sc
, tprm
);
1638 arg
= arg
->optimize(WANTvalue
, (p
->storageClass
& (STCref
| STCout
)) != 0);
1641 if (p
->storageClass
& STCref
)
1643 arg
= arg
->toLvalue(sc
, arg
);
1645 // Look for mutable misaligned pointer, etc., in @safe mode
1646 err
|= checkUnsafeAccess(sc
, arg
, false, true);
1648 else if (p
->storageClass
& STCout
)
1650 Type
*t
= arg
->type
;
1651 if (!t
->isMutable() || !t
->isAssignable()) // check blit assignable
1653 arg
->error("cannot modify struct %s with immutable members", arg
->toChars());
1658 // Look for misaligned pointer, etc., in @safe mode
1659 err
|= checkUnsafeAccess(sc
, arg
, false, true);
1660 err
|= checkDefCtor(arg
->loc
, t
); // t must be default constructible
1662 arg
= arg
->toLvalue(sc
, arg
);
1664 else if (p
->storageClass
& STClazy
)
1666 // Convert lazy argument to a delegate
1667 if (p
->type
->ty
== Tvoid
)
1668 arg
= toDelegate(arg
, p
->type
, sc
);
1670 arg
= toDelegate(arg
, arg
->type
, sc
);
1673 //printf("arg: %s\n", arg->toChars());
1674 //printf("type: %s\n", arg->type->toChars());
1675 if (tf
->parameterEscapes(p
))
1677 /* Argument value can escape from the called function.
1678 * Check arg to see if it matters.
1680 if (global
.params
.vsafe
)
1681 err
|= checkParamArgumentEscape(sc
, fd
, p
->ident
, arg
, false);
1685 /* Argument value cannot escape from the called function.
1687 Expression
*a
= arg
;
1688 if (a
->op
== TOKcast
)
1689 a
= ((CastExp
*)a
)->e1
;
1691 if (a
->op
== TOKfunction
)
1693 /* Function literals can only appear once, so if this
1694 * appearance was scoped, there cannot be any others.
1696 FuncExp
*fe
= (FuncExp
*)a
;
1697 fe
->fd
->tookAddressOf
= 0;
1699 else if (a
->op
== TOKdelegate
)
1701 /* For passing a delegate to a scoped parameter,
1702 * this doesn't count as taking the address of it.
1703 * We only worry about 'escaping' references to the function.
1705 DelegateExp
*de
= (DelegateExp
*)a
;
1706 if (de
->e1
->op
== TOKvar
)
1707 { VarExp
*ve
= (VarExp
*)de
->e1
;
1708 FuncDeclaration
*f
= ve
->var
->isFuncDeclaration();
1710 { f
->tookAddressOf
--;
1711 //printf("tookAddressOf = %d\n", f->tookAddressOf);
1716 arg
= arg
->optimize(WANTvalue
, (p
->storageClass
& (STCref
| STCout
)) != 0);
1720 // These will be the trailing ... arguments
1722 // If not D linkage, do promotions
1723 if (tf
->linkage
!= LINKd
)
1725 // Promote bytes, words, etc., to ints
1726 arg
= integralPromotions(arg
, sc
);
1728 // Promote floats to doubles
1729 switch (arg
->type
->ty
)
1732 arg
= arg
->castTo(sc
, Type::tfloat64
);
1736 arg
= arg
->castTo(sc
, Type::timaginary64
);
1740 if (tf
->varargs
== 1)
1742 const char *p
= tf
->linkage
== LINKc
? "extern(C)" : "extern(C++)";
1743 if (arg
->type
->ty
== Tarray
)
1745 arg
->error("cannot pass dynamic arrays to %s vararg functions", p
);
1748 if (arg
->type
->ty
== Tsarray
)
1750 arg
->error("cannot pass static arrays to %s vararg functions", p
);
1756 // Do not allow types that need destructors
1757 if (arg
->type
->needsDestruction())
1759 arg
->error("cannot pass types that need destruction as variadic arguments");
1763 // Convert static arrays to dynamic arrays
1764 // BUG: I don't think this is right for D2
1765 Type
*tb
= arg
->type
->toBasetype();
1766 if (tb
->ty
== Tsarray
)
1768 TypeSArray
*ts
= (TypeSArray
*)tb
;
1769 Type
*ta
= ts
->next
->arrayOf();
1770 if (ts
->size(arg
->loc
) == 0)
1771 arg
= new NullExp(arg
->loc
, ta
);
1773 arg
= arg
->castTo(sc
, ta
);
1775 if (tb
->ty
== Tstruct
)
1777 //arg = callCpCtor(sc, arg);
1780 // Give error for overloaded function addresses
1781 if (arg
->op
== TOKsymoff
)
1782 { SymOffExp
*se
= (SymOffExp
*)arg
;
1783 if (se
->hasOverloads
&&
1784 !se
->var
->isFuncDeclaration()->isUnique())
1785 { arg
->error("function %s is overloaded", arg
->toChars());
1789 if (arg
->checkValue())
1791 arg
= arg
->optimize(WANTvalue
);
1793 (*arguments
)[i
] = arg
;
1796 /* Remaining problems:
1797 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
1798 * implemented by calling a function) we'll defer this for now.
1799 * 2. value structs (or static arrays of them) that need to be copy constructed
1800 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
1801 * function gets called (functions normally destroy their parameters)
1802 * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
1803 * up properly. Pushing arguments on the stack then cannot fail.
1807 /* TODO: tackle problem 1)
1809 const bool leftToRight
= true; // TODO: something like !fd.isArrayOp
1811 assert(nargs
== nparams
); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
1813 const ptrdiff_t start
= (leftToRight
? 0 : (ptrdiff_t)nargs
- 1);
1814 const ptrdiff_t end
= (leftToRight
? (ptrdiff_t)nargs
: -1);
1815 const ptrdiff_t step
= (leftToRight
? 1 : -1);
1817 /* Compute indices of last throwing argument and first arg needing destruction.
1818 * Used to not set up destructors unless an arg needs destruction on a throw
1819 * in a later argument.
1821 ptrdiff_t lastthrow
= -1;
1822 ptrdiff_t firstdtor
= -1;
1823 for (ptrdiff_t i
= start
; i
!= end
; i
+= step
)
1825 Expression
*arg
= (*arguments
)[i
];
1826 if (canThrow(arg
, sc
->func
, false))
1828 if (firstdtor
== -1 && arg
->type
->needsDestruction())
1830 Parameter
*p
= (i
>= (ptrdiff_t)nparams
? NULL
: Parameter::getNth(tf
->parameters
, i
));
1831 if (!(p
&& (p
->storageClass
& (STClazy
| STCref
| STCout
))))
1836 /* Does problem 3) apply to this call?
1838 const bool needsPrefix
= (firstdtor
>= 0 && lastthrow
>= 0
1839 && (lastthrow
- firstdtor
) * step
> 0);
1841 /* If so, initialize 'eprefix' by declaring the gate
1843 VarDeclaration
*gate
= NULL
;
1846 // eprefix => bool __gate [= false]
1847 Identifier
*idtmp
= Identifier::generateId("__gate");
1848 gate
= new VarDeclaration(loc
, Type::tbool
, idtmp
, NULL
);
1849 gate
->storage_class
|= STCtemp
| STCctfe
| STCvolatile
;
1852 Expression
*ae
= new DeclarationExp(loc
, gate
);
1853 eprefix
= semantic(ae
, sc
);
1856 for (ptrdiff_t i
= start
; i
!= end
; i
+= step
)
1858 Expression
*arg
= (*arguments
)[i
];
1860 Parameter
*parameter
= (i
>= (ptrdiff_t)nparams
? NULL
: Parameter::getNth(tf
->parameters
, i
));
1861 const bool isRef
= (parameter
&& (parameter
->storageClass
& (STCref
| STCout
)));
1862 const bool isLazy
= (parameter
&& (parameter
->storageClass
& STClazy
));
1864 /* Skip lazy parameters
1869 /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
1870 * Declare a temporary variable for this arg and append that declaration to 'eprefix',
1871 * which will implicitly take care of potential problem 2) for this arg.
1872 * 'eprefix' will therefore finally contain all args up to and including the last
1873 * potentially throwing arg, excluding all lazy parameters.
1877 const bool needsDtor
= (!isRef
&& arg
->type
->needsDestruction() && i
!= lastthrow
);
1879 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
1881 VarDeclaration
*tmp
= copyToTemp(0,
1882 needsDtor
? "__pfx" : "__pfy",
1883 !isRef
? arg
: arg
->addressOf());
1886 /* Modify the destructor so it only runs if gate==false, i.e.,
1887 * only if there was a throw while constructing the args
1893 assert(i
== lastthrow
);
1899 // edtor => (__gate || edtor)
1901 Expression
*e
= tmp
->edtor
;
1902 e
= new OrOrExp(e
->loc
, new VarExp(e
->loc
, gate
), e
);
1903 tmp
->edtor
= semantic(e
, sc
);
1904 //printf("edtor: %s\n", tmp->edtor->toChars());
1907 // eprefix => (eprefix, auto __pfx/y = arg)
1908 DeclarationExp
*ae
= new DeclarationExp(loc
, tmp
);
1909 eprefix
= Expression::combine(eprefix
, semantic(ae
, sc
));
1912 arg
= new VarExp(loc
, tmp
);
1913 arg
= semantic(arg
, sc
);
1916 arg
= new PtrExp(loc
, arg
);
1917 arg
= semantic(arg
, sc
);
1920 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
1921 * i.e., disable the dtors right after constructing the last throwing arg.
1922 * From now on, the callee will take care of destructing the args because
1923 * the args are implicitly moved into function parameters.
1925 * Set gate to null to let the next iterations know they don't need to
1926 * append to eprefix anymore.
1930 Expression
*e
= new AssignExp(gate
->loc
, new VarExp(gate
->loc
, gate
), new IntegerExp(gate
->loc
, 1, Type::tbool
));
1931 eprefix
= Expression::combine(eprefix
, semantic(e
, sc
));
1937 /* No gate, no prefix to append to.
1938 * Handle problem 2) by calling the copy constructor for value structs
1939 * (or static arrays of them) if appropriate.
1941 Type
*tv
= arg
->type
->baseElemOf();
1942 if (!isRef
&& tv
->ty
== Tstruct
)
1943 arg
= doCopyOrMove(sc
, arg
);
1946 (*arguments
)[i
] = arg
;
1949 //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
1951 // If D linkage and variadic, add _arguments[] as first argument
1952 if (tf
->linkage
== LINKd
&& tf
->varargs
== 1)
1954 assert(arguments
->dim
>= nparams
);
1956 Parameters
*args
= new Parameters
;
1957 args
->setDim(arguments
->dim
- nparams
);
1958 for (size_t i
= 0; i
< arguments
->dim
- nparams
; i
++)
1960 Parameter
*arg
= new Parameter(STCin
, (*arguments
)[nparams
+ i
]->type
, NULL
, NULL
);
1964 TypeTuple
*tup
= new TypeTuple(args
);
1965 Expression
*e
= new TypeidExp(loc
, tup
);
1966 e
= semantic(e
, sc
);
1967 arguments
->insert(0, e
);
1970 Type
*tret
= tf
->next
;
1973 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
1974 // wildmatch, tf->isWild(), fd->isolateReturn());
1977 assert(sc
->intypeof
|| global
.errors
);
1978 tthis
= fd
->isThis()->type
->addMod(fd
->type
->mod
);
1980 if (tf
->isWild() && !fd
->isolateReturn())
1983 tret
= tret
->substWildTo(wildmatch
);
1985 if (!tret
->implicitConvTo(tthis
) &&
1986 !(MODimplicitConv(tret
->mod
, tthis
->mod
) && tret
->isBaseOf(tthis
, &offset
) && offset
== 0))
1988 const char* s1
= tret
->isNaked() ? " mutable" : tret
->modToChars();
1989 const char* s2
= tthis
->isNaked() ? " mutable" : tthis
->modToChars();
1990 ::error(loc
, "inout constructor %s creates%s object, not%s",
1991 fd
->toPrettyChars(), s1
, s2
);
1997 else if (wildmatch
&& tret
)
1999 /* Adjust function return type based on wildmatch
2001 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
2002 tret
= tret
->substWildTo(wildmatch
);
2005 *peprefix
= eprefix
;
2006 return (err
|| olderrors
!= global
.errors
);
2009 /******************************** Expression **************************/
2011 Expression::Expression(Loc loc
, TOK op
, int size
)
2013 //printf("Expression::Expression(op = %d) this = %p\n", op, this);
2016 this->size
= (unsigned char)size
;
2021 void Expression::_init()
2023 CTFEExp::cantexp
= new CTFEExp(TOKcantexp
);
2024 CTFEExp::voidexp
= new CTFEExp(TOKvoidexp
);
2025 CTFEExp::breakexp
= new CTFEExp(TOKbreak
);
2026 CTFEExp::continueexp
= new CTFEExp(TOKcontinue
);
2027 CTFEExp::gotoexp
= new CTFEExp(TOKgoto
);
2030 Expression
*Expression::syntaxCopy()
2032 //printf("Expression::syntaxCopy()\n");
2037 /*********************************
2038 * Does *not* do a deep copy.
2041 Expression
*Expression::copy()
2048 void *pe
= mem
.xmalloc(size
);
2049 //printf("Expression::copy(op = %d) e = %p\n", op, pe);
2050 e
= (Expression
*)memcpy(pe
, (void *)this, size
);
2054 void Expression::print()
2056 fprintf(stderr
, "%s\n", toChars());
2060 const char *Expression::toChars()
2064 toCBuffer(this, &buf
, &hgs
);
2065 return buf
.extractString();
2068 void Expression::error(const char *format
, ...) const
2070 if (type
!= Type::terror
)
2073 va_start(ap
, format
);
2074 ::verror(loc
, format
, ap
);
2079 void Expression::warning(const char *format
, ...) const
2081 if (type
!= Type::terror
)
2084 va_start(ap
, format
);
2085 ::vwarning(loc
, format
, ap
);
2090 void Expression::deprecation(const char *format
, ...) const
2092 if (type
!= Type::terror
)
2095 va_start(ap
, format
);
2096 ::vdeprecation(loc
, format
, ap
);
2101 /**********************************
2102 * Combine e1 and e2 by CommaExp if both are not NULL.
2104 Expression
*Expression::combine(Expression
*e1
, Expression
*e2
)
2110 e1
= new CommaExp(e1
->loc
, e1
, e2
);
2111 e1
->type
= e2
->type
;
2119 /**********************************
2120 * If 'e' is a tree of commas, returns the leftmost expression
2121 * by stripping off it from the tree. The remained part of the tree
2122 * is returned via *pe0.
2123 * Otherwise 'e' is directly returned and *pe0 is set to NULL.
2125 Expression
*Expression::extractLast(Expression
*e
, Expression
**pe0
)
2127 if (e
->op
!= TOKcomma
)
2133 CommaExp
*ce
= (CommaExp
*)e
;
2134 if (ce
->e2
->op
!= TOKcomma
)
2143 Expression
**pce
= &ce
->e2
;
2144 while (((CommaExp
*)(*pce
))->e2
->op
== TOKcomma
)
2146 pce
= &((CommaExp
*)(*pce
))->e2
;
2148 assert((*pce
)->op
== TOKcomma
);
2149 ce
= (CommaExp
*)(*pce
);
2156 dinteger_t
Expression::toInteger()
2158 //printf("Expression %s\n", Token::toChars(op));
2159 error("integer constant expression expected instead of %s", toChars());
2163 uinteger_t
Expression::toUInteger()
2165 //printf("Expression %s\n", Token::toChars(op));
2166 return (uinteger_t
)toInteger();
2169 real_t
Expression::toReal()
2171 error("floating point constant expression expected instead of %s", toChars());
2172 return CTFloat::zero
;
2175 real_t
Expression::toImaginary()
2177 error("floating point constant expression expected instead of %s", toChars());
2178 return CTFloat::zero
;
2181 complex_t
Expression::toComplex()
2183 error("floating point constant expression expected instead of %s", toChars());
2184 return complex_t(CTFloat::zero
);
2187 StringExp
*Expression::toStringExp()
2192 /***************************************
2193 * Return !=0 if expression is an lvalue.
2196 bool Expression::isLvalue()
2201 /*******************************
2202 * Give error if we're not an lvalue.
2203 * If we can, convert expression to be an lvalue.
2206 Expression
*Expression::toLvalue(Scope
*, Expression
*e
)
2210 else if (!loc
.filename
)
2213 if (e
->op
== TOKtype
)
2214 error("%s '%s' is a type, not an lvalue", e
->type
->kind(), e
->type
->toChars());
2216 error("%s is not an lvalue", e
->toChars());
2218 return new ErrorExp();
2221 /***************************************
2224 * flag: 1: do not issue error message for invalid modification
2226 * 0: is not modifiable
2227 * 1: is modifiable in default == being related to type->isMutable()
2228 * 2: is modifiable, because this is a part of initializing.
2231 int Expression::checkModifiable(Scope
*, int)
2233 return type
? 1 : 0; // default modifiable
2236 Expression
*Expression::modifiableLvalue(Scope
*sc
, Expression
*e
)
2238 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
2240 // See if this expression is a modifiable lvalue (i.e. not const)
2241 if (checkModifiable(sc
) == 1)
2244 if (!type
->isMutable())
2246 error("cannot modify %s expression %s", MODtoChars(type
->mod
), toChars());
2247 return new ErrorExp();
2249 else if (!type
->isAssignable())
2251 error("cannot modify struct %s %s with immutable members", toChars(), type
->toChars());
2252 return new ErrorExp();
2255 return toLvalue(sc
, e
);
2258 /****************************************
2259 * Check that the expression has a valid type.
2260 * If not, generates an error "... has no type".
2262 * true if the expression is not valid.
2264 * When this function returns true, `checkValue()` should also return true.
2266 bool Expression::checkType()
2271 /****************************************
2272 * Check that the expression has a valid value.
2273 * If not, generates an error "... has no value".
2275 * true if the expression is not valid or has void type.
2277 bool Expression::checkValue()
2279 if (type
&& type
->toBasetype()->ty
== Tvoid
)
2281 error("expression %s is void and has no value", toChars());
2284 type
= Type::terror
;
2290 bool Expression::checkScalar()
2294 if (type
->toBasetype()->ty
== Terror
)
2296 if (!type
->isscalar())
2298 error("'%s' is not a scalar, it is a %s", toChars(), type
->toChars());
2301 return checkValue();
2304 bool Expression::checkNoBool()
2308 if (type
->toBasetype()->ty
== Terror
)
2310 if (type
->toBasetype()->ty
== Tbool
)
2312 error("operation not allowed on bool '%s'", toChars());
2318 bool Expression::checkIntegral()
2322 if (type
->toBasetype()->ty
== Terror
)
2324 if (!type
->isintegral())
2326 error("'%s' is not of integral type, it is a %s", toChars(), type
->toChars());
2329 return checkValue();
2332 bool Expression::checkArithmetic()
2336 if (type
->toBasetype()->ty
== Terror
)
2338 if (!type
->isintegral() && !type
->isfloating())
2340 error("'%s' is not of arithmetic type, it is a %s", toChars(), type
->toChars());
2343 return checkValue();
2346 void Expression::checkDeprecated(Scope
*sc
, Dsymbol
*s
)
2348 s
->checkDeprecated(loc
, sc
);
2351 /*********************************************
2352 * Calling function f.
2353 * Check the purity, i.e. if we're in a pure function
2354 * we can only call other pure functions.
2355 * Returns true if error occurs.
2357 bool Expression::checkPurity(Scope
*sc
, FuncDeclaration
*f
)
2363 if (sc
->intypeof
== 1)
2365 if (sc
->flags
& (SCOPEctfe
| SCOPEdebug
))
2371 * /+pure+/ void h() {
2372 * /+pure+/ void i() { }
2376 * g() can call h() but not f()
2377 * i() can call h() and g() but not f()
2380 // Find the closest pure parent of the calling function
2381 FuncDeclaration
*outerfunc
= sc
->func
;
2382 FuncDeclaration
*calledparent
= f
;
2384 if (outerfunc
->isInstantiated())
2386 // The attributes of outerfunc should be inferred from the call of f.
2388 else if (f
->isInstantiated())
2390 // The attributes of f are inferred from its body.
2392 else if (f
->isFuncLiteralDeclaration())
2394 // The attributes of f are always inferred in its declared place.
2398 /* Today, static local functions are impure by default, but they cannot
2399 * violate purity of enclosing functions.
2401 * auto foo() pure { // non instantiated funciton
2402 * static auto bar() { // static, without pure attribute
2403 * impureFunc(); // impure call
2404 * // Although impureFunc is called inside bar, f(= impureFunc)
2405 * // is not callable inside pure outerfunc(= foo <- bar).
2409 * // Although bar is called inside foo, f(= bar) is callable
2410 * // bacause calledparent(= foo) is same with outerfunc(= foo).
2414 while (outerfunc
->toParent2() &&
2415 outerfunc
->isPureBypassingInference() == PUREimpure
&&
2416 outerfunc
->toParent2()->isFuncDeclaration())
2418 outerfunc
= outerfunc
->toParent2()->isFuncDeclaration();
2419 if (outerfunc
->type
->ty
== Terror
)
2422 while (calledparent
->toParent2() &&
2423 calledparent
->isPureBypassingInference() == PUREimpure
&&
2424 calledparent
->toParent2()->isFuncDeclaration())
2426 calledparent
= calledparent
->toParent2()->isFuncDeclaration();
2427 if (calledparent
->type
->ty
== Terror
)
2432 // If the caller has a pure parent, then either the called func must be pure,
2433 // OR, they must have the same pure parent.
2434 if (!f
->isPure() && calledparent
!= outerfunc
)
2436 FuncDeclaration
*ff
= outerfunc
;
2437 if (sc
->flags
& SCOPEcompile
? ff
->isPureBypassingInference() >= PUREweak
: ff
->setImpure())
2439 error("pure %s '%s' cannot call impure %s '%s'",
2440 ff
->kind(), ff
->toPrettyChars(), f
->kind(), f
->toPrettyChars());
2447 /*******************************************
2448 * Accessing variable v.
2449 * Check for purity and safety violations.
2450 * Returns true if error occurs.
2452 bool Expression::checkPurity(Scope
*sc
, VarDeclaration
*v
)
2454 //printf("v = %s %s\n", v->type->toChars(), v->toChars());
2456 /* Look for purity and safety violations when accessing variable v
2457 * from current function.
2461 if (sc
->intypeof
== 1)
2462 return false; // allow violations inside typeof(expression)
2463 if (sc
->flags
& (SCOPEctfe
| SCOPEdebug
))
2464 return false; // allow violations inside compile-time evaluated expressions and debug conditionals
2465 if (v
->ident
== Id::ctfe
)
2466 return false; // magic variable never violates pure and safe
2467 if (v
->isImmutable())
2468 return false; // always safe and pure to access immutables...
2469 if (v
->isConst() && !v
->isRef() && (v
->isDataseg() || v
->isParameter()) &&
2470 v
->type
->implicitConvTo(v
->type
->immutableOf()))
2471 return false; // or const global/parameter values which have no mutable indirections
2472 if (v
->storage_class
& STCmanifest
)
2473 return false; // ...or manifest constants
2478 // Bugzilla 7533: Accessing implicit generated __gate is pure.
2479 if (v
->ident
== Id::gate
)
2482 /* Accessing global mutable state.
2483 * Therefore, this function and all its immediately enclosing
2484 * functions must be pure.
2486 /* Today, static local functions are impure by default, but they cannot
2487 * violate purity of enclosing functions.
2489 * auto foo() pure { // non instantiated funciton
2490 * static auto bar() { // static, without pure attribute
2491 * globalData++; // impure access
2492 * // Although globalData is accessed inside bar,
2493 * // it is not accessible inside pure foo.
2497 for (Dsymbol
*s
= sc
->func
; s
; s
= s
->toParent2())
2499 FuncDeclaration
*ff
= s
->isFuncDeclaration();
2502 if (sc
->flags
& SCOPEcompile
? ff
->isPureBypassingInference() >= PUREweak
: ff
->setImpure())
2504 error("pure %s '%s' cannot access mutable static data '%s'",
2505 ff
->kind(), ff
->toPrettyChars(), v
->toChars());
2509 /* If the enclosing is an instantiated function or a lambda, its
2510 * attribute inference result is preferred.
2512 if (ff
->isInstantiated())
2514 if (ff
->isFuncLiteralDeclaration())
2525 * /+pure+/ void h() {
2527 * /+pure+/ void i() { }
2531 * i() can modify hx and gx but not fx
2534 Dsymbol
*vparent
= v
->toParent2();
2535 for (Dsymbol
*s
= sc
->func
; !err
&& s
; s
= s
->toParent2())
2540 if (AggregateDeclaration
*ad
= s
->isAggregateDeclaration())
2546 FuncDeclaration
*ff
= s
->isFuncDeclaration();
2549 if (ff
->isNested() || ff
->isThis())
2551 if (ff
->type
->isImmutable() ||
2552 (ff
->type
->isShared() && !MODimplicitConv(ff
->type
->mod
, v
->type
->mod
)))
2556 MODMatchToBuffer(&ffbuf
, ff
->type
->mod
, v
->type
->mod
);
2557 MODMatchToBuffer(&vbuf
, v
->type
->mod
, ff
->type
->mod
);
2558 error("%s%s '%s' cannot access %sdata '%s'",
2559 ffbuf
.peekString(), ff
->kind(), ff
->toPrettyChars(), vbuf
.peekString(), v
->toChars());
2569 /* Do not allow safe functions to access __gshared data
2571 if (v
->storage_class
& STCgshared
)
2573 if (sc
->func
->setUnsafe())
2575 error("safe %s '%s' cannot access __gshared data '%s'",
2576 sc
->func
->kind(), sc
->func
->toChars(), v
->toChars());
2584 /*********************************************
2585 * Calling function f.
2586 * Check the safety, i.e. if we're in a @safe function
2587 * we can only call @safe or @trusted functions.
2588 * Returns true if error occurs.
2590 bool Expression::checkSafety(Scope
*sc
, FuncDeclaration
*f
)
2596 if (sc
->intypeof
== 1)
2598 if (sc
->flags
& SCOPEctfe
)
2601 if (!f
->isSafe() && !f
->isTrusted())
2603 if (sc
->flags
& SCOPEcompile
? sc
->func
->isSafeBypassingInference() : sc
->func
->setUnsafe())
2605 if (loc
.linnum
== 0) // e.g. implicitly generated dtor
2606 loc
= sc
->func
->loc
;
2608 error("@safe %s '%s' cannot call @system %s '%s'",
2609 sc
->func
->kind(), sc
->func
->toPrettyChars(), f
->kind(), f
->toPrettyChars());
2616 /*********************************************
2617 * Calling function f.
2618 * Check the @nogc-ness, i.e. if we're in a @nogc function
2619 * we can only call other @nogc functions.
2620 * Returns true if error occurs.
2622 bool Expression::checkNogc(Scope
*sc
, FuncDeclaration
*f
)
2628 if (sc
->intypeof
== 1)
2630 if (sc
->flags
& SCOPEctfe
)
2635 if (sc
->flags
& SCOPEcompile
? sc
->func
->isNogcBypassingInference() : sc
->func
->setGC())
2637 if (loc
.linnum
== 0) // e.g. implicitly generated dtor
2638 loc
= sc
->func
->loc
;
2640 error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
2641 sc
->func
->kind(), sc
->func
->toPrettyChars(), f
->kind(), f
->toPrettyChars());
2648 /********************************************
2649 * Check that the postblit is callable if t is an array of structs.
2650 * Returns true if error happens.
2652 bool Expression::checkPostblit(Scope
*sc
, Type
*t
)
2654 t
= t
->baseElemOf();
2655 if (t
->ty
== Tstruct
)
2657 // Bugzilla 11395: Require TypeInfo generation for array concatenation
2658 semanticTypeInfo(sc
, t
);
2660 StructDeclaration
*sd
= ((TypeStruct
*)t
)->sym
;
2663 if (sd
->postblit
->storage_class
& STCdisable
)
2665 sd
->error(loc
, "is not copyable because it is annotated with @disable");
2668 //checkDeprecated(sc, sd->postblit); // necessary?
2669 checkPurity(sc
, sd
->postblit
);
2670 checkSafety(sc
, sd
->postblit
);
2671 checkNogc(sc
, sd
->postblit
);
2672 //checkAccess(sd, loc, sc, sd->postblit); // necessary?
2679 bool Expression::checkRightThis(Scope
*sc
)
2683 if (op
== TOKvar
&& type
->ty
!= Terror
)
2685 VarExp
*ve
= (VarExp
*)this;
2686 if (isNeedThisScope(sc
, ve
->var
))
2688 //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
2689 // sc->intypeof, sc->getStructClassScope(), func, fdthis);
2690 error("need 'this' for '%s' of type '%s'", ve
->var
->toChars(), ve
->var
->type
->toChars());
2697 /*******************************
2698 * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
2699 * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
2700 * Returns true if error occurs.
2702 bool Expression::checkReadModifyWrite(TOK rmwOp
, Expression
*ex
)
2704 //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex->toChars() : "");
2705 if (!type
|| !type
->isShared())
2708 // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
2712 case TOKpreplusplus
:
2717 case TOKpreminusminus
:
2725 deprecation("read-modify-write operations are not allowed for shared variables. "
2726 "Use core.atomic.atomicOp!\"%s\"(%s, %s) instead.",
2727 Token::tochars
[rmwOp
], toChars(), ex
? ex
->toChars() : "1");
2730 // note: enable when deprecation becomes an error.
2734 /*****************************
2735 * If expression can be tested for true or false,
2736 * returns the modified expression.
2737 * Otherwise returns ErrorExp.
2739 Expression
*Expression::toBoolean(Scope
*sc
)
2741 // Default is 'yes' - do nothing
2742 Expression
*e
= this;
2744 Type
*tb
= type
->toBasetype();
2747 // Structs can be converted to bool using opCast(bool)()
2748 if (tb
->ty
== Tstruct
)
2750 AggregateDeclaration
*ad
= ((TypeStruct
*)tb
)->sym
;
2751 /* Don't really need to check for opCast first, but by doing so we
2752 * get better error messages if it isn't there.
2754 Dsymbol
*fd
= search_function(ad
, Id::_cast
);
2757 e
= new CastExp(loc
, e
, Type::tbool
);
2758 e
= semantic(e
, sc
);
2762 // Forward to aliasthis.
2763 if (ad
->aliasthis
&& tb
!= att
)
2765 if (!att
&& tb
->checkAliasThisRec())
2767 e
= resolveAliasThis(sc
, e
);
2769 tb
= e
->type
->toBasetype();
2774 if (!t
->isBoolean())
2776 if (tb
!= Type::terror
)
2777 error("expression %s of type %s does not have a boolean value", toChars(), t
->toChars());
2778 return new ErrorExp();
2783 /******************************
2784 * Take address of expression.
2787 Expression
*Expression::addressOf()
2789 //printf("Expression::addressOf()\n");
2790 Expression
*e
= new AddrExp(loc
, this);
2791 e
->type
= type
->pointerTo();
2795 /******************************
2796 * If this is a reference, dereference it.
2799 Expression
*Expression::deref()
2801 //printf("Expression::deref()\n");
2802 // type could be null if forward referencing an 'auto' variable
2803 if (type
&& type
->ty
== Treference
)
2805 Expression
*e
= new PtrExp(loc
, this);
2806 e
->type
= ((TypeReference
*)type
)->next
;
2812 /********************************
2813 * Does this expression statically evaluate to a boolean 'result' (true or false)?
2815 bool Expression::isBool(bool)
2820 /****************************************
2821 * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc.
2824 Expression
*Expression::resolveLoc(Loc
, Scope
*)
2829 Expressions
*Expression::arraySyntaxCopy(Expressions
*exps
)
2831 Expressions
*a
= NULL
;
2834 a
= new Expressions();
2835 a
->setDim(exps
->dim
);
2836 for (size_t i
= 0; i
< a
->dim
; i
++)
2838 Expression
*e
= (*exps
)[i
];
2839 (*a
)[i
] = e
? e
->syntaxCopy() : NULL
;
2845 /************************************************
2846 * Destructors are attached to VarDeclarations.
2847 * Hence, if expression returns a temp that needs a destructor,
2848 * make sure and create a VarDeclaration for that temp.
2851 Expression
*Expression::addDtorHook(Scope
*)
2856 /******************************** IntegerExp **************************/
2858 IntegerExp::IntegerExp(Loc loc
, dinteger_t value
, Type
*type
)
2859 : Expression(loc
, TOKint64
, sizeof(IntegerExp
))
2861 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
2863 if (!type
->isscalar())
2865 //printf("%s, loc = %d\n", toChars(), loc.linnum);
2866 if (type
->ty
!= Terror
)
2867 error("integral constant must be scalar type, not %s", type
->toChars());
2868 type
= Type::terror
;
2874 IntegerExp::IntegerExp(dinteger_t value
)
2875 : Expression(Loc(), TOKint64
, sizeof(IntegerExp
))
2877 this->type
= Type::tint32
;
2878 this->value
= (d_int32
) value
;
2881 IntegerExp
*IntegerExp::create(Loc loc
, dinteger_t value
, Type
*type
)
2883 return new IntegerExp(loc
, value
, type
);
2886 bool IntegerExp::equals(RootObject
*o
)
2890 if (((Expression
*)o
)->op
== TOKint64
)
2892 IntegerExp
*ne
= (IntegerExp
*)o
;
2893 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
2902 void IntegerExp::setInteger(dinteger_t value
)
2904 this->value
= value
;
2908 void IntegerExp::normalize()
2910 /* 'Normalize' the value of the integer to be in range of the type
2912 switch (type
->toBasetype()->ty
)
2914 case Tbool
: value
= (value
!= 0); break;
2915 case Tint8
: value
= (d_int8
) value
; break;
2917 case Tuns8
: value
= (d_uns8
) value
; break;
2918 case Tint16
: value
= (d_int16
) value
; break;
2920 case Tuns16
: value
= (d_uns16
) value
; break;
2921 case Tint32
: value
= (d_int32
) value
; break;
2923 case Tuns32
: value
= (d_uns32
) value
; break;
2924 case Tint64
: value
= (d_int64
) value
; break;
2925 case Tuns64
: value
= (d_uns64
) value
; break;
2927 if (Target::ptrsize
== 4)
2928 value
= (d_uns32
) value
;
2929 else if (Target::ptrsize
== 8)
2930 value
= (d_uns64
) value
;
2939 dinteger_t
IntegerExp::toInteger()
2941 normalize(); // necessary until we fix all the paints of 'type'
2945 real_t
IntegerExp::toReal()
2947 normalize(); // necessary until we fix all the paints of 'type'
2948 Type
*t
= type
->toBasetype();
2949 if (t
->ty
== Tuns64
)
2950 return ldouble((d_uns64
)value
);
2952 return ldouble((d_int64
)value
);
2955 real_t
IntegerExp::toImaginary()
2957 return CTFloat::zero
;
2960 complex_t
IntegerExp::toComplex()
2962 return (complex_t
)toReal();
2965 bool IntegerExp::isBool(bool result
)
2967 bool r
= toInteger() != 0;
2968 return result
? r
: !r
;
2971 Expression
*IntegerExp::toLvalue(Scope
*, Expression
*e
)
2975 else if (!loc
.filename
)
2977 e
->error("constant %s is not an lvalue", e
->toChars());
2978 return new ErrorExp();
2981 /******************************** ErrorExp **************************/
2983 /* Use this expression for error recovery.
2984 * It should behave as a 'sink' to prevent further cascaded error messages.
2987 ErrorExp::ErrorExp()
2988 : Expression(Loc(), TOKerror
, sizeof(ErrorExp
))
2990 type
= Type::terror
;
2993 Expression
*ErrorExp::toLvalue(Scope
*, Expression
*)
2998 /******************************** RealExp **************************/
3000 RealExp::RealExp(Loc loc
, real_t value
, Type
*type
)
3001 : Expression(loc
, TOKfloat64
, sizeof(RealExp
))
3003 //printf("RealExp::RealExp(%Lg)\n", value);
3004 this->value
= value
;
3008 RealExp
*RealExp::create(Loc loc
, real_t value
, Type
*type
)
3010 return new RealExp(loc
, value
,type
);
3013 dinteger_t
RealExp::toInteger()
3015 return (sinteger_t
) toReal();
3018 uinteger_t
RealExp::toUInteger()
3020 return (uinteger_t
) toReal();
3023 real_t
RealExp::toReal()
3025 return type
->isreal() ? value
: CTFloat::zero
;
3028 real_t
RealExp::toImaginary()
3030 return type
->isreal() ? CTFloat::zero
: value
;
3033 complex_t
RealExp::toComplex()
3035 return complex_t(toReal(), toImaginary());
3038 /********************************
3039 * Test to see if two reals are the same.
3040 * Regard NaN's as equivalent.
3041 * Regard +0 and -0 as different.
3044 int RealEquals(real_t x1
, real_t x2
)
3046 return (CTFloat::isNaN(x1
) && CTFloat::isNaN(x2
)) ||
3047 CTFloat::isIdentical(x1
, x2
);
3050 bool RealExp::equals(RootObject
*o
)
3054 if (((Expression
*)o
)->op
== TOKfloat64
)
3056 RealExp
*ne
= (RealExp
*)o
;
3057 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
3058 RealEquals(value
, ne
->value
))
3066 bool RealExp::isBool(bool result
)
3068 return result
? (bool)value
: !(bool)value
;
3071 /******************************** ComplexExp **************************/
3073 ComplexExp::ComplexExp(Loc loc
, complex_t value
, Type
*type
)
3074 : Expression(loc
, TOKcomplex80
, sizeof(ComplexExp
)), value(value
)
3077 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
3080 ComplexExp
*ComplexExp::create(Loc loc
, complex_t value
, Type
*type
)
3082 return new ComplexExp(loc
, value
, type
);
3085 dinteger_t
ComplexExp::toInteger()
3087 return (sinteger_t
) toReal();
3090 uinteger_t
ComplexExp::toUInteger()
3092 return (uinteger_t
) toReal();
3095 real_t
ComplexExp::toReal()
3097 return creall(value
);
3100 real_t
ComplexExp::toImaginary()
3102 return cimagl(value
);
3105 complex_t
ComplexExp::toComplex()
3110 bool ComplexExp::equals(RootObject
*o
)
3114 if (((Expression
*)o
)->op
== TOKcomplex80
)
3116 ComplexExp
*ne
= (ComplexExp
*)o
;
3117 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
3118 RealEquals(creall(value
), creall(ne
->value
)) &&
3119 RealEquals(cimagl(value
), cimagl(ne
->value
)))
3127 bool ComplexExp::isBool(bool result
)
3130 return (bool)(value
);
3135 /******************************** IdentifierExp **************************/
3137 IdentifierExp::IdentifierExp(Loc loc
, Identifier
*ident
)
3138 : Expression(loc
, TOKidentifier
, sizeof(IdentifierExp
))
3140 this->ident
= ident
;
3143 IdentifierExp
*IdentifierExp::create(Loc loc
, Identifier
*ident
)
3145 return new IdentifierExp(loc
, ident
);
3148 bool IdentifierExp::isLvalue()
3153 Expression
*IdentifierExp::toLvalue(Scope
*, Expression
*)
3158 /******************************** DollarExp **************************/
3160 DollarExp::DollarExp(Loc loc
)
3161 : IdentifierExp(loc
, Id::dollar
)
3165 /******************************** DsymbolExp **************************/
3167 DsymbolExp::DsymbolExp(Loc loc
, Dsymbol
*s
, bool hasOverloads
)
3168 : Expression(loc
, TOKdsymbol
, sizeof(DsymbolExp
))
3171 this->hasOverloads
= hasOverloads
;
3174 /****************************************
3175 * Resolve a symbol `s` and wraps it in an expression object.
3177 * hasOverloads = works if the aliased symbol is a function.
3178 * true: it's overloaded and will be resolved later.
3179 * false: it's exact function symbol.
3181 Expression
*resolve(Loc loc
, Scope
*sc
, Dsymbol
*s
, bool hasOverloads
)
3186 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
3187 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
3189 Declaration
*d
= s
->isDeclaration();
3190 if (d
&& (d
->storage_class
& STCtemplateparameter
))
3196 if (!s
->isFuncDeclaration()) // functions are checked after overloading
3197 s
->checkDeprecated(loc
, sc
);
3199 // Bugzilla 12023: if 's' is a tuple variable, the tuple is returned.
3202 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
3203 if (s
!= olds
&& !s
->isFuncDeclaration())
3204 s
->checkDeprecated(loc
, sc
);
3207 if (EnumMember
*em
= s
->isEnumMember())
3209 return em
->getVarExp(loc
, sc
);
3211 if (VarDeclaration
*v
= s
->isVarDeclaration())
3213 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
3214 if (!v
->type
|| // during variable type inference
3215 (!v
->type
->deco
&& v
->inuse
)) // during variable type semantic
3217 if (v
->inuse
) // variable type depends on the variable itself
3218 ::error(loc
, "circular reference to %s '%s'", v
->kind(), v
->toPrettyChars());
3219 else // variable type cannot be determined
3220 ::error(loc
, "forward reference to %s '%s'", v
->kind(), v
->toPrettyChars());
3221 return new ErrorExp();
3223 if (v
->type
->ty
== Terror
)
3224 return new ErrorExp();
3226 if ((v
->storage_class
& STCmanifest
) && v
->_init
)
3230 ::error(loc
, "circular initialization of %s '%s'", v
->kind(), v
->toPrettyChars());
3231 return new ErrorExp();
3234 e
= v
->expandInitializer(loc
);
3236 e
= semantic(e
, sc
);
3241 // Change the ancestor lambdas to delegate before hasThis(sc) call.
3242 if (v
->checkNestedReference(sc
, loc
))
3243 return new ErrorExp();
3245 if (v
->needThis() && hasThis(sc
))
3246 e
= new DotVarExp(loc
, new ThisExp(loc
), v
);
3248 e
= new VarExp(loc
, v
);
3249 e
= semantic(e
, sc
);
3252 if (FuncLiteralDeclaration
*fld
= s
->isFuncLiteralDeclaration())
3254 //printf("'%s' is a function literal\n", fld->toChars());
3255 e
= new FuncExp(loc
, fld
);
3256 return semantic(e
, sc
);
3258 if (FuncDeclaration
*f
= s
->isFuncDeclaration())
3260 f
= f
->toAliasFunc();
3261 if (!f
->functionSemantic())
3262 return new ErrorExp();
3264 if (!hasOverloads
&& f
->checkForwardRef(loc
))
3265 return new ErrorExp();
3267 FuncDeclaration
*fd
= s
->isFuncDeclaration();
3269 return new VarExp(loc
, fd
, hasOverloads
);
3271 if (OverDeclaration
*od
= s
->isOverDeclaration())
3273 e
= new VarExp(loc
, od
, true);
3274 e
->type
= Type::tvoid
;
3277 if (OverloadSet
*o
= s
->isOverloadSet())
3279 //printf("'%s' is an overload set\n", o->toChars());
3280 return new OverExp(loc
, o
);
3283 if (Import
*imp
= s
->isImport())
3287 ::error(loc
, "forward reference of import %s", imp
->toChars());
3288 return new ErrorExp();
3290 ScopeExp
*ie
= new ScopeExp(loc
, imp
->pkg
);
3291 return semantic(ie
, sc
);
3293 if (Package
*pkg
= s
->isPackage())
3295 ScopeExp
*ie
= new ScopeExp(loc
, pkg
);
3296 return semantic(ie
, sc
);
3298 if (Module
*mod
= s
->isModule())
3300 ScopeExp
*ie
= new ScopeExp(loc
, mod
);
3301 return semantic(ie
, sc
);
3304 if (Nspace
*ns
= s
->isNspace())
3306 ScopeExp
*ie
= new ScopeExp(loc
, ns
);
3307 return semantic(ie
, sc
);
3310 if (Type
*t
= s
->getType())
3312 return semantic(new TypeExp(loc
, t
), sc
);
3315 if (TupleDeclaration
*tup
= s
->isTupleDeclaration())
3317 if (tup
->needThis() && hasThis(sc
))
3318 e
= new DotVarExp(loc
, new ThisExp(loc
), tup
);
3320 e
= new TupleExp(loc
, tup
);
3321 e
= semantic(e
, sc
);
3325 if (TemplateInstance
*ti
= s
->isTemplateInstance())
3328 if (!ti
->inst
|| ti
->errors
)
3329 return new ErrorExp();
3331 if (!s
->isTemplateInstance())
3333 e
= new ScopeExp(loc
, ti
);
3334 e
= semantic(e
, sc
);
3337 if (TemplateDeclaration
*td
= s
->isTemplateDeclaration())
3339 Dsymbol
*p
= td
->toParent2();
3340 FuncDeclaration
*fdthis
= hasThis(sc
);
3341 AggregateDeclaration
*ad
= p
? p
->isAggregateDeclaration() : NULL
;
3342 if (fdthis
&& ad
&& isAggregate(fdthis
->vthis
->type
) == ad
&&
3343 (td
->_scope
->stc
& STCstatic
) == 0)
3345 e
= new DotTemplateExp(loc
, new ThisExp(loc
), td
);
3348 e
= new TemplateExp(loc
, td
);
3349 e
= semantic(e
, sc
);
3353 ::error(loc
, "%s '%s' is not a variable", s
->kind(), s
->toChars());
3354 return new ErrorExp();
3357 bool DsymbolExp::isLvalue()
3362 Expression
*DsymbolExp::toLvalue(Scope
*, Expression
*)
3367 /******************************** ThisExp **************************/
3369 ThisExp::ThisExp(Loc loc
)
3370 : Expression(loc
, TOKthis
, sizeof(ThisExp
))
3372 //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
3376 bool ThisExp::isBool(bool result
)
3378 return result
? true : false;
3381 bool ThisExp::isLvalue()
3383 // Class `this` should be an rvalue; struct `this` should be an lvalue.
3384 return type
->toBasetype()->ty
!= Tclass
;
3387 Expression
*ThisExp::toLvalue(Scope
*sc
, Expression
*e
)
3389 if (type
->toBasetype()->ty
== Tclass
)
3391 // Class `this` is an rvalue; struct `this` is an lvalue.
3392 return Expression::toLvalue(sc
, e
);
3397 /******************************** SuperExp **************************/
3399 SuperExp::SuperExp(Loc loc
)
3405 /******************************** NullExp **************************/
3407 NullExp::NullExp(Loc loc
, Type
*type
)
3408 : Expression(loc
, TOKnull
, sizeof(NullExp
))
3414 bool NullExp::equals(RootObject
*o
)
3416 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
)
3418 Expression
*e
= (Expression
*)o
;
3419 if (e
->op
== TOKnull
&&
3420 type
->equals(e
->type
))
3428 bool NullExp::isBool(bool result
)
3430 return result
? false : true;
3433 StringExp
*NullExp::toStringExp()
3435 if (implicitConvTo(Type::tstring
))
3437 StringExp
*se
= new StringExp(loc
, (char*)mem
.xcalloc(1, 1), 0);
3438 se
->type
= Type::tstring
;
3444 /******************************** StringExp **************************/
3446 StringExp::StringExp(Loc loc
, char *string
)
3447 : Expression(loc
, TOKstring
, sizeof(StringExp
))
3449 this->string
= string
;
3450 this->len
= strlen(string
);
3452 this->committed
= 0;
3454 this->ownedByCtfe
= OWNEDcode
;
3457 StringExp::StringExp(Loc loc
, void *string
, size_t len
)
3458 : Expression(loc
, TOKstring
, sizeof(StringExp
))
3460 this->string
= string
;
3463 this->committed
= 0;
3465 this->ownedByCtfe
= OWNEDcode
;
3468 StringExp::StringExp(Loc loc
, void *string
, size_t len
, utf8_t postfix
)
3469 : Expression(loc
, TOKstring
, sizeof(StringExp
))
3471 this->string
= string
;
3474 this->committed
= 0;
3475 this->postfix
= postfix
;
3476 this->ownedByCtfe
= OWNEDcode
;
3479 StringExp
*StringExp::create(Loc loc
, char *s
)
3481 return new StringExp(loc
, s
);
3484 StringExp
*StringExp::create(Loc loc
, void *string
, size_t len
)
3486 return new StringExp(loc
, string
, len
);
3489 bool StringExp::equals(RootObject
*o
)
3491 //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
3492 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
)
3494 Expression
*e
= (Expression
*)o
;
3495 if (e
->op
== TOKstring
)
3497 return compare(o
) == 0;
3503 /**********************************
3504 * Return the number of code units the string would be if it were re-encoded
3507 * tynto = code unit type of the target encoding
3509 * number of code units
3512 size_t StringExp::numberOfCodeUnits(int tynto
) const
3518 case Tchar
: encSize
= 1; break;
3519 case Twchar
: encSize
= 2; break;
3520 case Tdchar
: encSize
= 4; break;
3533 for (size_t u
= 0; u
< len
;)
3535 if (const char *p
= utf_decodeChar((utf8_t
*)string
, len
, &u
, &c
))
3540 result
+= utf_codeLength(encSize
, c
);
3545 for (size_t u
= 0; u
< len
;)
3547 if (const char *p
= utf_decodeWchar((utf16_t
*)string
, len
, &u
, &c
))
3552 result
+= utf_codeLength(encSize
, c
);
3557 for (size_t u
= 0; u
< len
;)
3559 c
= *((utf32_t
*)((char *)string
+ u
));
3561 result
+= utf_codeLength(encSize
, c
);
3571 /**********************************************
3572 * Write the contents of the string to dest.
3573 * Use numberOfCodeUnits() to determine size of result.
3575 * dest = destination
3576 * tyto = encoding type of the result
3577 * zero = add terminating 0
3579 void StringExp::writeTo(void *dest
, bool zero
, int tyto
) const
3584 case 0: encSize
= sz
; break;
3585 case Tchar
: encSize
= 1; break;
3586 case Twchar
: encSize
= 2; break;
3587 case Tdchar
: encSize
= 4; break;
3593 memcpy(dest
, string
, len
* sz
);
3595 memset((char *)dest
+ len
* sz
, 0, sz
);
3601 /**************************************************
3602 * If the string data is UTF-8 and can be accessed directly,
3603 * return a pointer to it.
3604 * Do not assume a terminating 0.
3606 * pointer to string data if possible, null if not
3608 char *StringExp::toPtr()
3610 return (sz
== 1) ? (char*)string
: NULL
;
3613 StringExp
*StringExp::toStringExp()
3618 /****************************************
3619 * Convert string to char[].
3622 StringExp
*StringExp::toUTF8(Scope
*sc
)
3625 { // Convert to UTF-8 string
3627 Expression
*e
= castTo(sc
, Type::tchar
->arrayOf());
3628 e
= e
->optimize(WANTvalue
);
3629 assert(e
->op
== TOKstring
);
3630 StringExp
*se
= (StringExp
*)e
;
3631 assert(se
->sz
== 1);
3637 int StringExp::compare(RootObject
*obj
)
3639 //printf("StringExp::compare()\n");
3640 // Used to sort case statement expressions so we can do an efficient lookup
3641 StringExp
*se2
= (StringExp
*)(obj
);
3643 // This is a kludge so isExpression() in template.c will return 5
3648 assert(se2
->op
== TOKstring
);
3651 size_t len2
= se2
->len
;
3653 //printf("sz = %d, len1 = %d, len2 = %d\n", sz, (int)len1, (int)len2);
3659 return memcmp((char *)string
, (char *)se2
->string
, len1
);
3663 d_uns16
*s1
= (d_uns16
*)string
;
3664 d_uns16
*s2
= (d_uns16
*)se2
->string
;
3666 for (size_t u
= 0; u
< len
; u
++)
3669 return s1
[u
] - s2
[u
];
3676 d_uns32
*s1
= (d_uns32
*)string
;
3677 d_uns32
*s2
= (d_uns32
*)se2
->string
;
3679 for (size_t u
= 0; u
< len
; u
++)
3682 return s1
[u
] - s2
[u
];
3691 return (int)(len1
- len2
);
3694 bool StringExp::isBool(bool result
)
3696 return result
? true : false;
3700 bool StringExp::isLvalue()
3702 /* string literal is rvalue in default, but
3703 * conversion to reference of static array is only allowed.
3705 return (type
&& type
->toBasetype()->ty
== Tsarray
);
3708 Expression
*StringExp::toLvalue(Scope
*sc
, Expression
*e
)
3710 //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
3711 return (type
&& type
->toBasetype()->ty
== Tsarray
)
3712 ? this : Expression::toLvalue(sc
, e
);
3715 Expression
*StringExp::modifiableLvalue(Scope
*, Expression
*)
3717 error("cannot modify string literal %s", toChars());
3718 return new ErrorExp();
3721 unsigned StringExp::charAt(uinteger_t i
) const
3727 value
= ((utf8_t
*)string
)[(size_t)i
];
3731 value
= ((unsigned short *)string
)[(size_t)i
];
3735 value
= ((unsigned int *)string
)[(size_t)i
];
3745 /************************ ArrayLiteralExp ************************************/
3747 // [ e1, e2, e3, ... ]
3749 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expressions
*elements
)
3750 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
3753 this->elements
= elements
;
3754 this->ownedByCtfe
= OWNEDcode
;
3757 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expression
*e
)
3758 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
3761 elements
= new Expressions
;
3763 this->ownedByCtfe
= OWNEDcode
;
3766 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expression
*basis
, Expressions
*elements
)
3767 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
3769 this->basis
= basis
;
3770 this->elements
= elements
;
3771 this->ownedByCtfe
= OWNEDcode
;
3774 ArrayLiteralExp
*ArrayLiteralExp::create(Loc loc
, Expressions
*elements
)
3776 return new ArrayLiteralExp(loc
, elements
);
3779 bool ArrayLiteralExp::equals(RootObject
*o
)
3783 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
&&
3784 ((Expression
*)o
)->op
== TOKarrayliteral
)
3786 ArrayLiteralExp
*ae
= (ArrayLiteralExp
*)o
;
3787 if (elements
->dim
!= ae
->elements
->dim
)
3789 if (elements
->dim
== 0 &&
3790 !type
->equals(ae
->type
))
3794 for (size_t i
= 0; i
< elements
->dim
; i
++)
3796 Expression
*e1
= (*elements
)[i
];
3797 Expression
*e2
= (*ae
->elements
)[i
];
3803 (!e1
|| !e2
|| !e1
->equals(e2
)))
3811 Expression
*ArrayLiteralExp::syntaxCopy()
3813 return new ArrayLiteralExp(loc
,
3814 basis
? basis
->syntaxCopy() : NULL
,
3815 arraySyntaxCopy(elements
));
3818 Expression
*ArrayLiteralExp::getElement(d_size_t i
)
3820 Expression
*el
= (*elements
)[i
];
3826 static void appendArrayLiteral(Expressions
*elems
, ArrayLiteralExp
*ale
)
3830 size_t d
= elems
->dim
;
3831 elems
->append(ale
->elements
);
3832 for (size_t i
= d
; i
< elems
->dim
; i
++)
3834 Expression
*el
= (*elems
)[i
];
3836 (*elems
)[i
] = ale
->basis
;
3840 /* Copy element `Expressions` in the parameters when they're `ArrayLiteralExp`s.
3842 * e1 = If it's ArrayLiteralExp, its `elements` will be copied.
3843 * Otherwise, `e1` itself will be pushed into the new `Expressions`.
3844 * e2 = If it's not `null`, it will be pushed/appended to the new
3845 * `Expressions` by the same way with `e1`.
3847 * Newly allocated `Expressions`. Note that it points to the original
3848 * `Expression` values in e1 and e2.
3850 Expressions
* ArrayLiteralExp::copyElements(Expression
*e1
, Expression
*e2
)
3852 Expressions
*elems
= new Expressions();
3854 if (e1
->op
== TOKarrayliteral
)
3855 appendArrayLiteral(elems
, (ArrayLiteralExp
*)e1
);
3861 if (e2
->op
== TOKarrayliteral
)
3862 appendArrayLiteral(elems
, (ArrayLiteralExp
*)e2
);
3870 bool ArrayLiteralExp::isBool(bool result
)
3872 size_t dim
= elements
? elements
->dim
: 0;
3873 return result
? (dim
!= 0) : (dim
== 0);
3876 StringExp
*ArrayLiteralExp::toStringExp()
3878 TY telem
= type
->nextOf()->toBasetype()->ty
;
3880 if (telem
== Tchar
|| telem
== Twchar
|| telem
== Tdchar
||
3881 (telem
== Tvoid
&& (!elements
|| elements
->dim
== 0)))
3883 unsigned char sz
= 1;
3884 if (telem
== Twchar
) sz
= 2;
3885 else if (telem
== Tdchar
) sz
= 4;
3890 for (size_t i
= 0; i
< elements
->dim
; ++i
)
3892 Expression
*ch
= getElement(i
);
3893 if (ch
->op
!= TOKint64
)
3896 buf
.writeByte((unsigned)ch
->toInteger());
3898 buf
.writeword((unsigned)ch
->toInteger());
3900 buf
.write4((unsigned)ch
->toInteger());
3904 if (sz
== 1) { prefix
= 'c'; buf
.writeByte(0); }
3905 else if (sz
== 2) { prefix
= 'w'; buf
.writeword(0); }
3906 else { prefix
= 'd'; buf
.write4(0); }
3908 const size_t len
= buf
.offset
/ sz
- 1;
3909 StringExp
*se
= new StringExp(loc
, buf
.extractData(), len
, prefix
);
3917 /************************ AssocArrayLiteralExp ************************************/
3919 // [ key0 : value0, key1 : value1, ... ]
3921 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc
,
3922 Expressions
*keys
, Expressions
*values
)
3923 : Expression(loc
, TOKassocarrayliteral
, sizeof(AssocArrayLiteralExp
))
3925 assert(keys
->dim
== values
->dim
);
3927 this->values
= values
;
3928 this->ownedByCtfe
= OWNEDcode
;
3931 bool AssocArrayLiteralExp::equals(RootObject
*o
)
3935 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
&&
3936 ((Expression
*)o
)->op
== TOKassocarrayliteral
)
3938 AssocArrayLiteralExp
*ae
= (AssocArrayLiteralExp
*)o
;
3939 if (keys
->dim
!= ae
->keys
->dim
)
3942 for (size_t i
= 0; i
< keys
->dim
; i
++)
3944 for (size_t j
= 0; j
< ae
->keys
->dim
; j
++)
3946 if ((*keys
)[i
]->equals((*ae
->keys
)[j
]))
3948 if (!(*values
)[i
]->equals((*ae
->values
)[j
]))
3954 return count
== keys
->dim
;
3959 Expression
*AssocArrayLiteralExp::syntaxCopy()
3961 return new AssocArrayLiteralExp(loc
,
3962 arraySyntaxCopy(keys
), arraySyntaxCopy(values
));
3965 bool AssocArrayLiteralExp::isBool(bool result
)
3967 size_t dim
= keys
->dim
;
3968 return result
? (dim
!= 0) : (dim
== 0);
3971 /************************ StructLiteralExp ************************************/
3973 // sd( e1, e2, e3, ... )
3975 StructLiteralExp::StructLiteralExp(Loc loc
, StructDeclaration
*sd
, Expressions
*elements
, Type
*stype
)
3976 : Expression(loc
, TOKstructliteral
, sizeof(StructLiteralExp
))
3980 elements
= new Expressions();
3981 this->elements
= elements
;
3982 this->stype
= stype
;
3983 this->useStaticInit
= false;
3985 this->ownedByCtfe
= OWNEDcode
;
3986 this->origin
= this;
3987 this->stageflags
= 0;
3988 this->inlinecopy
= NULL
;
3989 //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars());
3992 StructLiteralExp
*StructLiteralExp::create(Loc loc
, StructDeclaration
*sd
, void *elements
, Type
*stype
)
3994 return new StructLiteralExp(loc
, sd
, (Expressions
*)elements
, stype
);
3997 bool StructLiteralExp::equals(RootObject
*o
)
4001 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
&&
4002 ((Expression
*)o
)->op
== TOKstructliteral
)
4004 StructLiteralExp
*se
= (StructLiteralExp
*)o
;
4005 if (!type
->equals(se
->type
))
4007 if (elements
->dim
!= se
->elements
->dim
)
4009 for (size_t i
= 0; i
< elements
->dim
; i
++)
4011 Expression
*e1
= (*elements
)[i
];
4012 Expression
*e2
= (*se
->elements
)[i
];
4014 (!e1
|| !e2
|| !e1
->equals(e2
)))
4022 Expression
*StructLiteralExp::syntaxCopy()
4024 StructLiteralExp
*exp
= new StructLiteralExp(loc
, sd
, arraySyntaxCopy(elements
), type
? type
: stype
);
4029 Expression
*StructLiteralExp::addDtorHook(Scope
*sc
)
4031 /* If struct requires a destructor, rewrite as:
4033 * so that the destructor can be hung on tmp.
4035 if (sd
->dtor
&& sc
->func
)
4037 /* Make an identifier for the temporary of the form:
4038 * __sl%s%d, where %s is the struct name
4040 const size_t len
= 10;
4043 strcpy(buf
, "__sl");
4044 strncat(buf
, sd
->ident
->toChars(), len
- 4 - 1);
4045 assert(buf
[len
] == 0);
4047 VarDeclaration
*tmp
= copyToTemp(0, buf
, this);
4048 Expression
*ae
= new DeclarationExp(loc
, tmp
);
4049 Expression
*e
= new CommaExp(loc
, ae
, new VarExp(loc
, tmp
));
4050 e
= semantic(e
, sc
);
4056 /**************************************
4057 * Gets expression at offset of type.
4058 * Returns NULL if not found.
4061 Expression
*StructLiteralExp::getField(Type
*type
, unsigned offset
)
4063 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
4064 // /*toChars()*/"", type->toChars(), offset);
4065 Expression
*e
= NULL
;
4066 int i
= getFieldIndex(type
, offset
);
4070 //printf("\ti = %d\n", i);
4071 if (i
== (int)sd
->fields
.dim
- 1 && sd
->isNested())
4074 assert(i
< (int)elements
->dim
);
4078 //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
4080 /* If type is a static array, and e is an initializer for that array,
4081 * then the field initializer should be an array literal of e.
4083 if (e
->type
->castMod(0) != type
->castMod(0) && type
->ty
== Tsarray
)
4084 { TypeSArray
*tsa
= (TypeSArray
*)type
;
4085 size_t length
= (size_t)tsa
->dim
->toInteger();
4086 Expressions
*z
= new Expressions
;
4088 for (size_t q
= 0; q
< length
; ++q
)
4089 (*z
)[q
] = e
->copy();
4090 e
= new ArrayLiteralExp(loc
, z
);
4098 if (useStaticInit
&& e
->op
== TOKstructliteral
&&
4099 e
->type
->needsNested())
4101 StructLiteralExp
*se
= (StructLiteralExp
*)e
;
4102 se
->useStaticInit
= true;
4109 /************************************
4110 * Get index of field.
4111 * Returns -1 if not found.
4114 int StructLiteralExp::getFieldIndex(Type
*type
, unsigned offset
)
4116 /* Find which field offset is by looking at the field offsets
4120 for (size_t i
= 0; i
< sd
->fields
.dim
; i
++)
4122 VarDeclaration
*v
= sd
->fields
[i
];
4124 if (offset
== v
->offset
&&
4125 type
->size() == v
->type
->size())
4127 /* context field might not be filled. */
4128 if (i
== sd
->fields
.dim
- 1 && sd
->isNested())
4130 Expression
*e
= (*elements
)[i
];
4142 /************************ TypeDotIdExp ************************************/
4151 DotIdExp
*typeDotIdExp(Loc loc
, Type
*type
, Identifier
*ident
)
4153 return new DotIdExp(loc
, new TypeExp(loc
, type
), ident
);
4157 /************************************************************/
4159 // Mainly just a placeholder
4161 TypeExp::TypeExp(Loc loc
, Type
*type
)
4162 : Expression(loc
, TOKtype
, sizeof(TypeExp
))
4164 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
4168 Expression
*TypeExp::syntaxCopy()
4170 return new TypeExp(loc
, type
->syntaxCopy());
4173 bool TypeExp::checkType()
4175 error("type %s is not an expression", toChars());
4179 bool TypeExp::checkValue()
4181 error("type %s has no value", toChars());
4185 /************************************************************/
4187 /***********************************************************
4188 * Mainly just a placeholder of
4189 * Package, Module, Nspace, and TemplateInstance (including TemplateMixin)
4191 * A template instance that requires IFTI:
4192 * foo!tiargs(fargs) // foo!tiargs
4193 * is left until CallExp::semantic() or resolveProperties()
4195 ScopeExp::ScopeExp(Loc loc
, ScopeDsymbol
*sds
)
4196 : Expression(loc
, TOKscope
, sizeof(ScopeExp
))
4198 //printf("ScopeExp::ScopeExp(sds = '%s')\n", sds->toChars());
4199 //static int count; if (++count == 38) *(char*)0=0;
4201 assert(!sds
->isTemplateDeclaration()); // instead, you should use TemplateExp
4204 Expression
*ScopeExp::syntaxCopy()
4206 return new ScopeExp(loc
, (ScopeDsymbol
*)sds
->syntaxCopy(NULL
));
4209 bool ScopeExp::checkType()
4211 if (sds
->isPackage())
4213 error("%s %s has no type", sds
->kind(), sds
->toChars());
4216 if (TemplateInstance
*ti
= sds
->isTemplateInstance())
4218 //assert(ti->needsTypeInference(sc));
4220 ti
->semantictiargsdone
&&
4221 ti
->semanticRun
== PASSinit
)
4223 error("partial %s %s has no type", sds
->kind(), toChars());
4230 bool ScopeExp::checkValue()
4232 error("%s %s has no value", sds
->kind(), sds
->toChars());
4236 /********************** TemplateExp **************************************/
4238 // Mainly just a placeholder
4240 TemplateExp::TemplateExp(Loc loc
, TemplateDeclaration
*td
, FuncDeclaration
*fd
)
4241 : Expression(loc
, TOKtemplate
, sizeof(TemplateExp
))
4243 //printf("TemplateExp(): %s\n", td->toChars());
4248 bool TemplateExp::checkType()
4250 error("%s %s has no type", td
->kind(), toChars());
4254 bool TemplateExp::checkValue()
4256 error("%s %s has no value", td
->kind(), toChars());
4260 bool TemplateExp::isLvalue()
4265 Expression
*TemplateExp::toLvalue(Scope
*sc
, Expression
*e
)
4268 return Expression::toLvalue(sc
, e
);
4271 return resolve(loc
, sc
, fd
, true);
4274 /********************** NewExp **************************************/
4276 /* thisexp.new(newargs) newtype(arguments) */
4278 NewExp::NewExp(Loc loc
, Expression
*thisexp
, Expressions
*newargs
,
4279 Type
*newtype
, Expressions
*arguments
)
4280 : Expression(loc
, TOKnew
, sizeof(NewExp
))
4282 this->thisexp
= thisexp
;
4283 this->newargs
= newargs
;
4284 this->newtype
= newtype
;
4285 this->arguments
= arguments
;
4292 NewExp
*NewExp::create(Loc loc
, Expression
*thisexp
, Expressions
*newargs
,
4293 Type
*newtype
, Expressions
*arguments
)
4295 return new NewExp(loc
, thisexp
, newargs
, newtype
, arguments
);
4298 Expression
*NewExp::syntaxCopy()
4300 return new NewExp(loc
,
4301 thisexp
? thisexp
->syntaxCopy() : NULL
,
4302 arraySyntaxCopy(newargs
),
4303 newtype
->syntaxCopy(), arraySyntaxCopy(arguments
));
4306 /********************** NewAnonClassExp **************************************/
4308 NewAnonClassExp::NewAnonClassExp(Loc loc
, Expression
*thisexp
,
4309 Expressions
*newargs
, ClassDeclaration
*cd
, Expressions
*arguments
)
4310 : Expression(loc
, TOKnewanonclass
, sizeof(NewAnonClassExp
))
4312 this->thisexp
= thisexp
;
4313 this->newargs
= newargs
;
4315 this->arguments
= arguments
;
4318 Expression
*NewAnonClassExp::syntaxCopy()
4320 return new NewAnonClassExp(loc
,
4321 thisexp
? thisexp
->syntaxCopy() : NULL
,
4322 arraySyntaxCopy(newargs
),
4323 (ClassDeclaration
*)cd
->syntaxCopy(NULL
),
4324 arraySyntaxCopy(arguments
));
4327 /********************** SymbolExp **************************************/
4329 SymbolExp::SymbolExp(Loc loc
, TOK op
, int size
, Declaration
*var
, bool hasOverloads
)
4330 : Expression(loc
, op
, size
)
4334 this->hasOverloads
= hasOverloads
;
4337 /********************** SymOffExp **************************************/
4339 SymOffExp::SymOffExp(Loc loc
, Declaration
*var
, dinteger_t offset
, bool hasOverloads
)
4340 : SymbolExp(loc
, TOKsymoff
, sizeof(SymOffExp
), var
,
4341 var
->isVarDeclaration() ? false : hasOverloads
)
4343 if (VarDeclaration
*v
= var
->isVarDeclaration())
4345 // FIXME: This error report will never be handled anyone.
4346 // It should be done before the SymOffExp construction.
4348 ::error(loc
, "need 'this' for address of %s", v
->toChars());
4350 this->offset
= offset
;
4353 bool SymOffExp::isBool(bool result
)
4355 return result
? true : false;
4358 /******************************** VarExp **************************/
4360 VarExp::VarExp(Loc loc
, Declaration
*var
, bool hasOverloads
)
4361 : SymbolExp(loc
, TOKvar
, sizeof(VarExp
), var
,
4362 var
->isVarDeclaration() ? false : hasOverloads
)
4364 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
4365 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
4366 this->type
= var
->type
;
4369 VarExp
*VarExp::create(Loc loc
, Declaration
*var
, bool hasOverloads
)
4371 return new VarExp(loc
, var
, hasOverloads
);
4374 bool VarExp::equals(RootObject
*o
)
4378 if (((Expression
*)o
)->op
== TOKvar
)
4380 VarExp
*ne
= (VarExp
*)o
;
4381 if (type
->toHeadMutable()->equals(ne
->type
->toHeadMutable()) &&
4390 bool VarExp::isLvalue()
4392 if (var
->storage_class
& (STClazy
| STCrvalue
| STCmanifest
))
4397 Expression
*VarExp::toLvalue(Scope
*, Expression
*)
4399 if (var
->storage_class
& STCmanifest
)
4401 error("manifest constant '%s' is not lvalue", var
->toChars());
4402 return new ErrorExp();
4404 if (var
->storage_class
& STClazy
)
4406 error("lazy variables cannot be lvalues");
4407 return new ErrorExp();
4409 if (var
->ident
== Id::ctfe
)
4411 error("compiler-generated variable __ctfe is not an lvalue");
4412 return new ErrorExp();
4414 if (var
->ident
== Id::dollar
) // Bugzilla 13574
4416 error("'$' is not an lvalue");
4417 return new ErrorExp();
4422 int VarExp::checkModifiable(Scope
*sc
, int flag
)
4424 //printf("VarExp::checkModifiable %s", toChars());
4426 return var
->checkModify(loc
, sc
, type
, NULL
, flag
);
4429 Expression
*VarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
4431 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
4432 if (var
->storage_class
& STCmanifest
)
4434 error("cannot modify manifest constant '%s'", toChars());
4435 return new ErrorExp();
4437 // See if this expression is a modifiable lvalue (i.e. not const)
4438 return Expression::modifiableLvalue(sc
, e
);
4442 /******************************** OverExp **************************/
4444 OverExp::OverExp(Loc loc
, OverloadSet
*s
)
4445 : Expression(loc
, TOKoverloadset
, sizeof(OverExp
))
4447 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
4452 bool OverExp::isLvalue()
4457 Expression
*OverExp::toLvalue(Scope
*, Expression
*)
4462 /******************************** TupleExp **************************/
4464 TupleExp::TupleExp(Loc loc
, Expression
*e0
, Expressions
*exps
)
4465 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
4467 //printf("TupleExp(this = %p)\n", this);
4472 TupleExp::TupleExp(Loc loc
, Expressions
*exps
)
4473 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
4475 //printf("TupleExp(this = %p)\n", this);
4480 TupleExp::TupleExp(Loc loc
, TupleDeclaration
*tup
)
4481 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
4484 this->exps
= new Expressions();
4486 this->exps
->reserve(tup
->objects
->dim
);
4487 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
4488 { RootObject
*o
= (*tup
->objects
)[i
];
4489 if (Dsymbol
*s
= getDsymbol(o
))
4491 /* If tuple element represents a symbol, translate to DsymbolExp
4492 * to supply implicit 'this' if needed later.
4494 Expression
*e
= new DsymbolExp(loc
, s
);
4495 this->exps
->push(e
);
4497 else if (o
->dyncast() == DYNCAST_EXPRESSION
)
4499 Expression
*e
= ((Expression
*)o
)->copy();
4500 e
->loc
= loc
; // Bugzilla 15669
4501 this->exps
->push(e
);
4503 else if (o
->dyncast() == DYNCAST_TYPE
)
4505 Type
*t
= (Type
*)o
;
4506 Expression
*e
= new TypeExp(loc
, t
);
4507 this->exps
->push(e
);
4511 error("%s is not an expression", o
->toChars());
4516 bool TupleExp::equals(RootObject
*o
)
4520 if (((Expression
*)o
)->op
== TOKtuple
)
4522 TupleExp
*te
= (TupleExp
*)o
;
4523 if (exps
->dim
!= te
->exps
->dim
)
4525 if ((e0
&& !e0
->equals(te
->e0
)) || (!e0
&& te
->e0
))
4527 for (size_t i
= 0; i
< exps
->dim
; i
++)
4529 Expression
*e1
= (*exps
)[i
];
4530 Expression
*e2
= (*te
->exps
)[i
];
4531 if (!e1
->equals(e2
))
4539 Expression
*TupleExp::syntaxCopy()
4541 return new TupleExp(loc
, e0
? e0
->syntaxCopy() : NULL
, arraySyntaxCopy(exps
));
4544 /******************************** FuncExp *********************************/
4546 FuncExp::FuncExp(Loc loc
, Dsymbol
*s
)
4547 : Expression(loc
, TOKfunction
, sizeof(FuncExp
))
4549 this->td
= s
->isTemplateDeclaration();
4550 this->fd
= s
->isFuncLiteralDeclaration();
4553 assert(td
->literal
);
4554 assert(td
->members
&& td
->members
->dim
== 1);
4555 fd
= (*td
->members
)[0]->isFuncLiteralDeclaration();
4557 tok
= fd
->tok
; // save original kind of function/delegate/(infer)
4561 bool FuncExp::equals(RootObject
*o
)
4565 if (o
->dyncast() != DYNCAST_EXPRESSION
)
4567 if (((Expression
*)o
)->op
== TOKfunction
)
4569 FuncExp
*fe
= (FuncExp
*)o
;
4570 return fd
== fe
->fd
;
4575 void FuncExp::genIdent(Scope
*sc
)
4577 if (fd
->ident
== Id::empty
)
4580 if (fd
->fes
) s
= "__foreachbody";
4581 else if (fd
->tok
== TOKreserved
) s
= "__lambda";
4582 else if (fd
->tok
== TOKdelegate
) s
= "__dgliteral";
4583 else s
= "__funcliteral";
4585 DsymbolTable
*symtab
;
4586 if (FuncDeclaration
*func
= sc
->parent
->isFuncDeclaration())
4588 if (func
->localsymtab
== NULL
)
4590 // Inside template constraint, symtab is not set yet.
4591 // Initialize it lazily.
4592 func
->localsymtab
= new DsymbolTable();
4594 symtab
= func
->localsymtab
;
4598 ScopeDsymbol
*sds
= sc
->parent
->isScopeDsymbol();
4601 // Inside template constraint, symtab may not be set yet.
4602 // Initialize it lazily.
4603 assert(sds
->isTemplateInstance());
4604 sds
->symtab
= new DsymbolTable();
4606 symtab
= sds
->symtab
;
4609 int num
= (int)dmd_aaLen(symtab
->tab
) + 1;
4610 Identifier
*id
= Identifier::generateId(s
, num
);
4612 if (td
) td
->ident
= id
;
4613 symtab
->insert(td
? (Dsymbol
*)td
: (Dsymbol
*)fd
);
4617 Expression
*FuncExp::syntaxCopy()
4620 return new FuncExp(loc
, td
->syntaxCopy(NULL
));
4621 else if (fd
->semanticRun
== PASSinit
)
4622 return new FuncExp(loc
, fd
->syntaxCopy(NULL
));
4623 else // Bugzilla 13481: Prevent multiple semantic analysis of lambda body.
4624 return new FuncExp(loc
, fd
);
4627 MATCH
FuncExp::matchType(Type
*to
, Scope
*sc
, FuncExp
**presult
, int flag
)
4629 //printf("FuncExp::matchType('%s'), to=%s\n", type ? type->toChars() : "null", to->toChars());
4633 TypeFunction
*tof
= NULL
;
4634 if (to
->ty
== Tdelegate
)
4636 if (tok
== TOKfunction
)
4639 error("cannot match function literal to delegate type '%s'", to
->toChars());
4640 return MATCHnomatch
;
4642 tof
= (TypeFunction
*)to
->nextOf();
4644 else if (to
->ty
== Tpointer
&& to
->nextOf()->ty
== Tfunction
)
4646 if (tok
== TOKdelegate
)
4649 error("cannot match delegate literal to function pointer type '%s'", to
->toChars());
4650 return MATCHnomatch
;
4652 tof
= (TypeFunction
*)to
->nextOf();
4661 error("cannot infer parameter types from %s", to
->toChars());
4662 return MATCHnomatch
;
4665 // Parameter types inference from 'tof'
4667 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
4668 //printf("\ttof = %s\n", tof->toChars());
4669 //printf("\ttf = %s\n", tf->toChars());
4670 size_t dim
= Parameter::dim(tf
->parameters
);
4672 if (Parameter::dim(tof
->parameters
) != dim
||
4673 tof
->varargs
!= tf
->varargs
)
4676 Objects
*tiargs
= new Objects();
4677 tiargs
->reserve(td
->parameters
->dim
);
4679 for (size_t i
= 0; i
< td
->parameters
->dim
; i
++)
4681 TemplateParameter
*tp
= (*td
->parameters
)[i
];
4683 for (; u
< dim
; u
++)
4685 Parameter
*p
= Parameter::getNth(tf
->parameters
, u
);
4686 if (p
->type
->ty
== Tident
&&
4687 ((TypeIdentifier
*)p
->type
)->ident
== tp
->ident
)
4693 Parameter
*pto
= Parameter::getNth(tof
->parameters
, u
);
4694 Type
*t
= pto
->type
;
4695 if (t
->ty
== Terror
)
4700 // Set target of return type inference
4701 if (!tf
->next
&& tof
->next
)
4704 TemplateInstance
*ti
= new TemplateInstance(loc
, td
, tiargs
);
4705 Expression
*ex
= new ScopeExp(loc
, ti
);
4706 ex
= ::semantic(ex
, td
->_scope
);
4708 // Reset inference target for the later re-semantic
4711 if (ex
->op
== TOKerror
)
4712 return MATCHnomatch
;
4713 if (ex
->op
!= TOKfunction
)
4715 return ((FuncExp
*)ex
)->matchType(to
, sc
, presult
, flag
);
4718 if (!tof
|| !tof
->next
)
4719 return MATCHnomatch
;
4721 assert(type
&& type
!= Type::tvoid
);
4722 TypeFunction
*tfx
= (TypeFunction
*)fd
->type
;
4723 bool convertMatch
= (type
->ty
!= to
->ty
);
4725 if (fd
->inferRetType
&& tfx
->next
->implicitConvTo(tof
->next
) == MATCHconvert
)
4727 /* If return type is inferred and covariant return,
4728 * tweak return statements to required return type.
4731 * class C : Object, I{}
4733 * I delegate() dg = delegate() { return new class C(); }
4735 convertMatch
= true;
4737 TypeFunction
*tfy
= new TypeFunction(tfx
->parameters
, tof
->next
, tfx
->varargs
, tfx
->linkage
, STCundefined
);
4738 tfy
->mod
= tfx
->mod
;
4739 tfy
->isnothrow
= tfx
->isnothrow
;
4740 tfy
->isnogc
= tfx
->isnogc
;
4741 tfy
->purity
= tfx
->purity
;
4742 tfy
->isproperty
= tfx
->isproperty
;
4743 tfy
->isref
= tfx
->isref
;
4744 tfy
->iswild
= tfx
->iswild
;
4745 tfy
->deco
= tfy
->merge()->deco
;
4751 if (tok
== TOKdelegate
||
4752 (tok
== TOKreserved
&& (type
->ty
== Tdelegate
||
4753 (type
->ty
== Tpointer
&& to
->ty
== Tdelegate
))))
4755 // Allow conversion from implicit function pointer to delegate
4756 tx
= new TypeDelegate(tfx
);
4757 tx
->deco
= tx
->merge()->deco
;
4761 assert(tok
== TOKfunction
||
4762 (tok
== TOKreserved
&& type
->ty
== Tpointer
));
4763 tx
= tfx
->pointerTo();
4765 //printf("\ttx = %s, to = %s\n", tx->toChars(), to->toChars());
4767 MATCH m
= tx
->implicitConvTo(to
);
4768 if (m
> MATCHnomatch
)
4770 // MATCHexact: exact type match
4771 // MATCHconst: covairiant type match (eg. attributes difference)
4772 // MATCHconvert: context conversion
4773 m
= convertMatch
? MATCHconvert
: tx
->equals(to
) ? MATCHexact
: MATCHconst
;
4777 (*presult
) = (FuncExp
*)copy();
4778 (*presult
)->type
= to
;
4780 // Bugzilla 12508: Tweak function body for covariant returns.
4781 (*presult
)->fd
->modifyReturns(sc
, tof
->next
);
4786 error("cannot implicitly convert expression (%s) of type %s to %s",
4787 toChars(), tx
->toChars(), to
->toChars());
4792 const char *FuncExp::toChars()
4794 return fd
->toChars();
4797 bool FuncExp::checkType()
4801 error("template lambda has no type");
4807 bool FuncExp::checkValue()
4811 error("template lambda has no value");
4817 /******************************** DeclarationExp **************************/
4819 DeclarationExp::DeclarationExp(Loc loc
, Dsymbol
*declaration
)
4820 : Expression(loc
, TOKdeclaration
, sizeof(DeclarationExp
))
4822 this->declaration
= declaration
;
4825 Expression
*DeclarationExp::syntaxCopy()
4827 return new DeclarationExp(loc
, declaration
->syntaxCopy(NULL
));
4830 bool DeclarationExp::hasCode()
4832 if (VarDeclaration
*vd
= declaration
->isVarDeclaration())
4834 return !(vd
->storage_class
& (STCmanifest
| STCstatic
));
4839 /************************ TypeidExp ************************************/
4845 TypeidExp::TypeidExp(Loc loc
, RootObject
*o
)
4846 : Expression(loc
, TOKtypeid
, sizeof(TypeidExp
))
4851 Expression
*TypeidExp::syntaxCopy()
4853 return new TypeidExp(loc
, objectSyntaxCopy(obj
));
4856 /************************ TraitsExp ************************************/
4858 * __traits(identifier, args...)
4861 TraitsExp::TraitsExp(Loc loc
, Identifier
*ident
, Objects
*args
)
4862 : Expression(loc
, TOKtraits
, sizeof(TraitsExp
))
4864 this->ident
= ident
;
4868 Expression
*TraitsExp::syntaxCopy()
4870 return new TraitsExp(loc
, ident
, TemplateInstance::arraySyntaxCopy(args
));
4873 /************************************************************/
4875 HaltExp::HaltExp(Loc loc
)
4876 : Expression(loc
, TOKhalt
, sizeof(HaltExp
))
4880 /************************************************************/
4882 IsExp::IsExp(Loc loc
, Type
*targ
, Identifier
*id
, TOK tok
,
4883 Type
*tspec
, TOK tok2
, TemplateParameters
*parameters
)
4884 : Expression(loc
, TOKis
, sizeof(IsExp
))
4889 this->tspec
= tspec
;
4891 this->parameters
= parameters
;
4894 Expression
*IsExp::syntaxCopy()
4896 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4897 TemplateParameters
*p
= NULL
;
4900 p
= new TemplateParameters();
4901 p
->setDim(parameters
->dim
);
4902 for (size_t i
= 0; i
< p
->dim
; i
++)
4903 (*p
)[i
] = (*parameters
)[i
]->syntaxCopy();
4905 return new IsExp(loc
,
4909 tspec
? tspec
->syntaxCopy() : NULL
,
4914 void unSpeculative(Scope
*sc
, RootObject
*o
);
4916 /************************************************************/
4918 UnaExp::UnaExp(Loc loc
, TOK op
, int size
, Expression
*e1
)
4919 : Expression(loc
, op
, size
)
4925 Expression
*UnaExp::syntaxCopy()
4927 UnaExp
*e
= (UnaExp
*)copy();
4929 e
->e1
= e
->e1
->syntaxCopy();
4933 /********************************
4934 * The type for a unary expression is incompatible.
4935 * Print error message.
4939 Expression
*UnaExp::incompatibleTypes()
4941 if (e1
->type
->toBasetype() == Type::terror
)
4944 if (e1
->op
== TOKtype
)
4946 error("incompatible type for (%s(%s)): cannot use '%s' with types",
4947 Token::toChars(op
), e1
->toChars(), Token::toChars(op
));
4951 error("incompatible type for (%s(%s)): '%s'",
4952 Token::toChars(op
), e1
->toChars(), e1
->type
->toChars());
4954 return new ErrorExp();
4957 Expression
*UnaExp::resolveLoc(Loc loc
, Scope
*sc
)
4959 e1
= e1
->resolveLoc(loc
, sc
);
4963 /************************************************************/
4965 BinExp::BinExp(Loc loc
, TOK op
, int size
, Expression
*e1
, Expression
*e2
)
4966 : Expression(loc
, op
, size
)
4975 Expression
*BinExp::syntaxCopy()
4977 BinExp
*e
= (BinExp
*)copy();
4979 e
->e1
= e
->e1
->syntaxCopy();
4980 e
->e2
= e
->e2
->syntaxCopy();
4984 Expression
*BinExp::checkOpAssignTypes(Scope
*sc
)
4986 // At that point t1 and t2 are the merged types. type is the original type of the lhs.
4987 Type
*t1
= e1
->type
;
4988 Type
*t2
= e2
->type
;
4990 // T opAssign floating yields a floating. Prevent truncating conversions (float to int).
4992 // Should we also prevent double to float (type->isfloating() && type->size() < t2 ->size()) ?
4993 if (op
== TOKaddass
|| op
== TOKminass
||
4994 op
== TOKmulass
|| op
== TOKdivass
|| op
== TOKmodass
||
4997 if ((type
->isintegral() && t2
->isfloating()))
4999 warning("%s %s %s is performing truncating conversion",
5000 type
->toChars(), Token::toChars(op
), t2
->toChars());
5004 // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
5005 if (op
== TOKmulass
|| op
== TOKdivass
|| op
== TOKmodass
)
5007 // Any multiplication by an imaginary or complex number yields a complex result.
5008 // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
5009 const char *opstr
= Token::toChars(op
);
5010 if (t1
->isreal() && t2
->iscomplex())
5012 error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
5013 t1
->toChars(), opstr
, t2
->toChars(),
5014 t1
->toChars(), opstr
, t2
->toChars());
5015 return new ErrorExp();
5017 else if (t1
->isimaginary() && t2
->iscomplex())
5019 error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
5020 t1
->toChars(), opstr
, t2
->toChars(),
5021 t1
->toChars(), opstr
, t2
->toChars());
5022 return new ErrorExp();
5024 else if ((t1
->isreal() || t1
->isimaginary()) &&
5027 error("%s %s %s is an undefined operation", t1
->toChars(), opstr
, t2
->toChars());
5028 return new ErrorExp();
5032 // generate an error if this is a nonsensical += or -=, eg real += imaginary
5033 if (op
== TOKaddass
|| op
== TOKminass
)
5035 // Addition or subtraction of a real and an imaginary is a complex result.
5036 // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
5037 if ((t1
->isreal() && (t2
->isimaginary() || t2
->iscomplex())) ||
5038 (t1
->isimaginary() && (t2
->isreal() || t2
->iscomplex())))
5040 error("%s %s %s is undefined (result is complex)",
5041 t1
->toChars(), Token::toChars(op
), t2
->toChars());
5042 return new ErrorExp();
5044 if (type
->isreal() || type
->isimaginary())
5046 assert(global
.errors
|| t2
->isfloating());
5047 e2
= e2
->castTo(sc
, t1
);
5051 if (op
== TOKmulass
)
5053 if (t2
->isfloating())
5057 if (t2
->isimaginary() || t2
->iscomplex())
5059 e2
= e2
->castTo(sc
, t1
);
5062 else if (t1
->isimaginary())
5064 if (t2
->isimaginary() || t2
->iscomplex())
5068 case Timaginary32
: t2
= Type::tfloat32
; break;
5069 case Timaginary64
: t2
= Type::tfloat64
; break;
5070 case Timaginary80
: t2
= Type::tfloat80
; break;
5074 e2
= e2
->castTo(sc
, t2
);
5079 else if (op
== TOKdivass
)
5081 if (t2
->isimaginary())
5086 // Therefore, the result is 0
5087 e2
= new CommaExp(loc
, e2
, new RealExp(loc
, CTFloat::zero
, t1
));
5089 Expression
*e
= new AssignExp(loc
, e1
, e2
);
5093 else if (t1
->isimaginary())
5098 case Timaginary32
: t3
= Type::tfloat32
; break;
5099 case Timaginary64
: t3
= Type::tfloat64
; break;
5100 case Timaginary80
: t3
= Type::tfloat80
; break;
5104 e2
= e2
->castTo(sc
, t3
);
5105 Expression
*e
= new AssignExp(loc
, e1
, e2
);
5111 else if (op
== TOKmodass
)
5113 if (t2
->iscomplex())
5115 error("cannot perform modulo complex arithmetic");
5116 return new ErrorExp();
5122 /********************************
5123 * The types for a binary expression are incompatible.
5124 * Print error message.
5128 Expression
*BinExp::incompatibleTypes()
5130 if (e1
->type
->toBasetype() == Type::terror
)
5132 if (e2
->type
->toBasetype() == Type::terror
)
5135 // CondExp uses 'a ? b : c' but we're comparing 'b : c'
5136 TOK thisOp
= (op
== TOKquestion
) ? TOKcolon
: op
;
5137 if (e1
->op
== TOKtype
|| e2
->op
== TOKtype
)
5139 error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types",
5140 e1
->toChars(), Token::toChars(thisOp
), e2
->toChars(), Token::toChars(op
));
5144 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
5145 e1
->toChars(), Token::toChars(thisOp
), e2
->toChars(),
5146 e1
->type
->toChars(), e2
->type
->toChars());
5148 return new ErrorExp();
5151 bool BinExp::checkIntegralBin()
5153 bool r1
= e1
->checkIntegral();
5154 bool r2
= e2
->checkIntegral();
5158 bool BinExp::checkArithmeticBin()
5160 bool r1
= e1
->checkArithmetic();
5161 bool r2
= e2
->checkArithmetic();
5165 /********************** BinAssignExp **************************************/
5167 BinAssignExp::BinAssignExp(Loc loc
, TOK op
, int size
, Expression
*e1
, Expression
*e2
)
5168 : BinExp(loc
, op
, size
, e1
, e2
)
5172 bool BinAssignExp::isLvalue()
5177 Expression
*BinAssignExp::toLvalue(Scope
*, Expression
*)
5179 // Lvalue-ness will be handled in glue layer.
5183 Expression
*BinAssignExp::modifiableLvalue(Scope
*sc
, Expression
*)
5185 // should check e1->checkModifiable() ?
5186 return toLvalue(sc
, this);
5189 /************************************************************/
5191 CompileExp::CompileExp(Loc loc
, Expression
*e
)
5192 : UnaExp(loc
, TOKmixin
, sizeof(CompileExp
), e
)
5196 /************************************************************/
5198 ImportExp::ImportExp(Loc loc
, Expression
*e
)
5199 : UnaExp(loc
, TOKimport
, sizeof(ImportExp
), e
)
5203 /************************************************************/
5205 AssertExp::AssertExp(Loc loc
, Expression
*e
, Expression
*msg
)
5206 : UnaExp(loc
, TOKassert
, sizeof(AssertExp
), e
)
5211 Expression
*AssertExp::syntaxCopy()
5213 return new AssertExp(loc
, e1
->syntaxCopy(), msg
? msg
->syntaxCopy() : NULL
);
5216 /************************************************************/
5218 DotIdExp::DotIdExp(Loc loc
, Expression
*e
, Identifier
*ident
)
5219 : UnaExp(loc
, TOKdotid
, sizeof(DotIdExp
), e
)
5221 this->ident
= ident
;
5222 this->wantsym
= false;
5223 this->noderef
= false;
5226 DotIdExp
*DotIdExp::create(Loc loc
, Expression
*e
, Identifier
*ident
)
5228 return new DotIdExp(loc
, e
, ident
);
5231 /********************** DotTemplateExp ***********************************/
5233 // Mainly just a placeholder
5235 DotTemplateExp::DotTemplateExp(Loc loc
, Expression
*e
, TemplateDeclaration
*td
)
5236 : UnaExp(loc
, TOKdottd
, sizeof(DotTemplateExp
), e
)
5242 /************************************************************/
5244 DotVarExp::DotVarExp(Loc loc
, Expression
*e
, Declaration
*var
, bool hasOverloads
)
5245 : UnaExp(loc
, TOKdotvar
, sizeof(DotVarExp
), e
)
5247 //printf("DotVarExp()\n");
5249 this->hasOverloads
= var
->isVarDeclaration() ? false : hasOverloads
;
5252 bool DotVarExp::isLvalue()
5257 Expression
*DotVarExp::toLvalue(Scope
*, Expression
*)
5259 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5263 /***********************************************
5264 * Mark variable v as modified if it is inside a constructor that var
5267 int modifyFieldVar(Loc loc
, Scope
*sc
, VarDeclaration
*var
, Expression
*e1
)
5269 //printf("modifyFieldVar(var = %s)\n", var->toChars());
5270 Dsymbol
*s
= sc
->func
;
5273 FuncDeclaration
*fd
= NULL
;
5275 fd
= s
->isFuncDeclaration();
5277 ((fd
->isCtorDeclaration() && var
->isField()) ||
5278 (fd
->isStaticCtorDeclaration() && !var
->isField())) &&
5279 fd
->toParent2() == var
->toParent2() &&
5280 (!e1
|| e1
->op
== TOKthis
)
5285 var
->ctorinit
= true;
5286 //printf("setting ctorinit\n");
5288 if (var
->isField() && sc
->fieldinit
&& !sc
->intypeof
)
5291 bool mustInit
= ((var
->storage_class
& STCnodefaultctor
) != 0 ||
5292 var
->type
->needsNested());
5294 size_t dim
= sc
->fieldinit_dim
;
5295 AggregateDeclaration
*ad
= fd
->isMember2();
5298 for (i
= 0; i
< dim
; i
++) // same as findFieldIndexByName in ctfeexp.c ?
5300 if (ad
->fields
[i
] == var
)
5304 unsigned fi
= sc
->fieldinit
[i
];
5306 if (fi
& CSXthis_ctor
)
5308 if (var
->type
->isMutable() && e1
->type
->isMutable())
5312 const char *modStr
= !var
->type
->isMutable() ? MODtoChars(var
->type
->mod
) : MODtoChars(e1
->type
->mod
);
5313 ::error(loc
, "%s field '%s' initialized multiple times", modStr
, var
->toChars());
5316 else if (sc
->noctor
|| (fi
& CSXlabel
))
5318 if (!mustInit
&& var
->type
->isMutable() && e1
->type
->isMutable())
5322 const char *modStr
= !var
->type
->isMutable() ? MODtoChars(var
->type
->mod
) : MODtoChars(e1
->type
->mod
);
5323 ::error(loc
, "%s field '%s' initialization is not allowed in loops or after labels", modStr
, var
->toChars());
5326 sc
->fieldinit
[i
] |= CSXthis_ctor
;
5327 if (var
->overlapped
) // Bugzilla 15258
5329 for (size_t j
= 0; j
< ad
->fields
.dim
; j
++)
5331 VarDeclaration
*v
= ad
->fields
[j
];
5332 if (v
== var
|| !var
->isOverlappedWith(v
))
5335 sc
->fieldinit
[j
] = CSXthis_ctor
;
5339 else if (fd
!= sc
->func
)
5341 if (var
->type
->isMutable())
5343 else if (sc
->func
->fes
)
5345 const char *p
= var
->isField() ? "field" : var
->kind();
5346 ::error(loc
, "%s %s '%s' initialization is not allowed in foreach loop",
5347 MODtoChars(var
->type
->mod
), p
, var
->toChars());
5351 const char *p
= var
->isField() ? "field" : var
->kind();
5352 ::error(loc
, "%s %s '%s' initialization is not allowed in nested function '%s'",
5353 MODtoChars(var
->type
->mod
), p
, var
->toChars(), sc
->func
->toChars());
5371 int DotVarExp::checkModifiable(Scope
*sc
, int flag
)
5373 //printf("DotVarExp::checkModifiable %s %s\n", toChars(), type->toChars());
5374 if (checkUnsafeAccess(sc
, this, false, !flag
))
5377 if (e1
->op
== TOKthis
)
5378 return var
->checkModify(loc
, sc
, type
, e1
, flag
);
5380 //printf("\te1 = %s\n", e1->toChars());
5381 return e1
->checkModifiable(sc
, flag
);
5384 Expression
*DotVarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5386 return Expression::modifiableLvalue(sc
, e
);
5389 /************************************************************/
5395 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc
, Expression
*e
, Identifier
*name
, Objects
*tiargs
)
5396 : UnaExp(loc
, TOKdotti
, sizeof(DotTemplateInstanceExp
), e
)
5398 //printf("DotTemplateInstanceExp()\n");
5399 this->ti
= new TemplateInstance(loc
, name
);
5400 this->ti
->tiargs
= tiargs
;
5403 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc
, Expression
*e
, TemplateInstance
*ti
)
5404 : UnaExp(loc
, TOKdotti
, sizeof(DotTemplateInstanceExp
), e
)
5409 Expression
*DotTemplateInstanceExp::syntaxCopy()
5411 return new DotTemplateInstanceExp(loc
,
5414 TemplateInstance::arraySyntaxCopy(ti
->tiargs
));
5417 bool DotTemplateInstanceExp::findTempDecl(Scope
*sc
)
5422 Expression
*e
= new DotIdExp(loc
, e1
, ti
->name
);
5423 e
= semantic(e
, sc
);
5424 if (e
->op
== TOKdot
)
5425 e
= ((DotExp
*)e
)->e2
;
5430 case TOKoverloadset
: s
= ((OverExp
*)e
)->vars
; break;
5431 case TOKdottd
: s
= ((DotTemplateExp
*)e
)->td
; break;
5432 case TOKscope
: s
= ((ScopeExp
*)e
)->sds
; break;
5433 case TOKdotvar
: s
= ((DotVarExp
*)e
)->var
; break;
5434 case TOKvar
: s
= ((VarExp
*)e
)->var
; break;
5435 default: return false;
5437 return ti
->updateTempDecl(sc
, s
);
5440 /************************************************************/
5442 DelegateExp::DelegateExp(Loc loc
, Expression
*e
, FuncDeclaration
*f
, bool hasOverloads
)
5443 : UnaExp(loc
, TOKdelegate
, sizeof(DelegateExp
), e
)
5446 this->hasOverloads
= hasOverloads
;
5449 /************************************************************/
5451 DotTypeExp::DotTypeExp(Loc loc
, Expression
*e
, Dsymbol
*s
)
5452 : UnaExp(loc
, TOKdottype
, sizeof(DotTypeExp
), e
)
5458 /************************************************************/
5460 CallExp::CallExp(Loc loc
, Expression
*e
, Expressions
*exps
)
5461 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5463 this->arguments
= exps
;
5465 this->directcall
= false;
5468 CallExp::CallExp(Loc loc
, Expression
*e
)
5469 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5471 this->arguments
= NULL
;
5473 this->directcall
= false;
5476 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
)
5477 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5479 Expressions
*arguments
= new Expressions();
5482 arguments
->setDim(1);
5483 (*arguments
)[0] = earg1
;
5485 this->arguments
= arguments
;
5487 this->directcall
= false;
5490 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
, Expression
*earg2
)
5491 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5493 Expressions
*arguments
= new Expressions();
5494 arguments
->setDim(2);
5495 (*arguments
)[0] = earg1
;
5496 (*arguments
)[1] = earg2
;
5498 this->arguments
= arguments
;
5500 this->directcall
= false;
5503 CallExp
*CallExp::create(Loc loc
, Expression
*e
, Expressions
*exps
)
5505 return new CallExp(loc
, e
, exps
);
5508 CallExp
*CallExp::create(Loc loc
, Expression
*e
)
5510 return new CallExp(loc
, e
);
5513 CallExp
*CallExp::create(Loc loc
, Expression
*e
, Expression
*earg1
)
5515 return new CallExp(loc
, e
, earg1
);
5518 Expression
*CallExp::syntaxCopy()
5520 return new CallExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
5523 bool CallExp::isLvalue()
5525 Type
*tb
= e1
->type
->toBasetype();
5526 if (tb
->ty
== Tdelegate
|| tb
->ty
== Tpointer
)
5528 if (tb
->ty
== Tfunction
&& ((TypeFunction
*)tb
)->isref
)
5530 if (e1
->op
== TOKdotvar
)
5531 if (((DotVarExp
*)e1
)->var
->isCtorDeclaration())
5533 return true; // function returns a reference
5538 Expression
*CallExp::toLvalue(Scope
*sc
, Expression
*e
)
5542 return Expression::toLvalue(sc
, e
);
5545 Expression
*CallExp::addDtorHook(Scope
*sc
)
5547 /* Only need to add dtor hook if it's a type that needs destruction.
5548 * Use same logic as VarDeclaration::callScopeDtor()
5551 if (e1
->type
&& e1
->type
->ty
== Tfunction
)
5553 TypeFunction
*tf
= (TypeFunction
*)e1
->type
;
5558 Type
*tv
= type
->baseElemOf();
5559 if (tv
->ty
== Tstruct
)
5561 TypeStruct
*ts
= (TypeStruct
*)tv
;
5562 StructDeclaration
*sd
= ts
->sym
;
5565 /* Type needs destruction, so declare a tmp
5566 * which the back end will recognize and call dtor on
5568 VarDeclaration
*tmp
= copyToTemp(0, "__tmpfordtor", this);
5569 DeclarationExp
*de
= new DeclarationExp(loc
, tmp
);
5570 VarExp
*ve
= new VarExp(loc
, tmp
);
5571 Expression
*e
= new CommaExp(loc
, de
, ve
);
5572 e
= semantic(e
, sc
);
5579 FuncDeclaration
*isFuncAddress(Expression
*e
, bool *hasOverloads
= NULL
)
5581 if (e
->op
== TOKaddress
)
5583 Expression
*ae1
= ((AddrExp
*)e
)->e1
;
5584 if (ae1
->op
== TOKvar
)
5586 VarExp
*ve
= (VarExp
*)ae1
;
5588 *hasOverloads
= ve
->hasOverloads
;
5589 return ve
->var
->isFuncDeclaration();
5591 if (ae1
->op
== TOKdotvar
)
5593 DotVarExp
*dve
= (DotVarExp
*)ae1
;
5595 *hasOverloads
= dve
->hasOverloads
;
5596 return dve
->var
->isFuncDeclaration();
5601 if (e
->op
== TOKsymoff
)
5603 SymOffExp
*soe
= (SymOffExp
*)e
;
5605 *hasOverloads
= soe
->hasOverloads
;
5606 return soe
->var
->isFuncDeclaration();
5608 if (e
->op
== TOKdelegate
)
5610 DelegateExp
*dge
= (DelegateExp
*)e
;
5612 *hasOverloads
= dge
->hasOverloads
;
5613 return dge
->func
->isFuncDeclaration();
5619 /************************************************************/
5621 AddrExp::AddrExp(Loc loc
, Expression
*e
)
5622 : UnaExp(loc
, TOKaddress
, sizeof(AddrExp
), e
)
5626 AddrExp::AddrExp(Loc loc
, Expression
*e
, Type
*t
)
5627 : UnaExp(loc
, TOKaddress
, sizeof(AddrExp
), e
)
5632 /************************************************************/
5634 PtrExp::PtrExp(Loc loc
, Expression
*e
)
5635 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
5638 // type = ((TypePointer *)e->type)->next;
5641 PtrExp::PtrExp(Loc loc
, Expression
*e
, Type
*t
)
5642 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
5647 bool PtrExp::isLvalue()
5652 Expression
*PtrExp::toLvalue(Scope
*, Expression
*)
5657 int PtrExp::checkModifiable(Scope
*sc
, int flag
)
5659 if (e1
->op
== TOKsymoff
)
5660 { SymOffExp
*se
= (SymOffExp
*)e1
;
5661 return se
->var
->checkModify(loc
, sc
, type
, NULL
, flag
);
5663 else if (e1
->op
== TOKaddress
)
5665 AddrExp
*ae
= (AddrExp
*)e1
;
5666 return ae
->e1
->checkModifiable(sc
, flag
);
5671 Expression
*PtrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5673 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
5674 return Expression::modifiableLvalue(sc
, e
);
5677 /************************************************************/
5679 NegExp::NegExp(Loc loc
, Expression
*e
)
5680 : UnaExp(loc
, TOKneg
, sizeof(NegExp
), e
)
5684 /************************************************************/
5686 UAddExp::UAddExp(Loc loc
, Expression
*e
)
5687 : UnaExp(loc
, TOKuadd
, sizeof(UAddExp
), e
)
5691 /************************************************************/
5693 ComExp::ComExp(Loc loc
, Expression
*e
)
5694 : UnaExp(loc
, TOKtilde
, sizeof(ComExp
), e
)
5698 /************************************************************/
5700 NotExp::NotExp(Loc loc
, Expression
*e
)
5701 : UnaExp(loc
, TOKnot
, sizeof(NotExp
), e
)
5705 /************************************************************/
5707 DeleteExp::DeleteExp(Loc loc
, Expression
*e
, bool isRAII
)
5708 : UnaExp(loc
, TOKdelete
, sizeof(DeleteExp
), e
)
5710 this->isRAII
= isRAII
;
5713 Expression
*DeleteExp::toBoolean(Scope
*)
5715 error("delete does not give a boolean result");
5716 return new ErrorExp();
5719 /************************************************************/
5721 CastExp::CastExp(Loc loc
, Expression
*e
, Type
*t
)
5722 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
5725 this->mod
= (unsigned char)~0;
5728 /* For cast(const) and cast(immutable)
5730 CastExp::CastExp(Loc loc
, Expression
*e
, unsigned char mod
)
5731 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
5737 Expression
*CastExp::syntaxCopy()
5739 return to
? new CastExp(loc
, e1
->syntaxCopy(), to
->syntaxCopy())
5740 : new CastExp(loc
, e1
->syntaxCopy(), mod
);
5743 /************************************************************/
5745 VectorExp::VectorExp(Loc loc
, Expression
*e
, Type
*t
)
5746 : UnaExp(loc
, TOKvector
, sizeof(VectorExp
), e
)
5748 assert(t
->ty
== Tvector
);
5749 to
= (TypeVector
*)t
;
5753 VectorExp
*VectorExp::create(Loc loc
, Expression
*e
, Type
*t
)
5755 return new VectorExp(loc
, e
, t
);
5758 Expression
*VectorExp::syntaxCopy()
5760 return new VectorExp(loc
, e1
->syntaxCopy(), to
->syntaxCopy());
5763 /************************************************************/
5765 SliceExp::SliceExp(Loc loc
, Expression
*e1
, IntervalExp
*ie
)
5766 : UnaExp(loc
, TOKslice
, sizeof(SliceExp
), e1
)
5768 this->upr
= ie
? ie
->upr
: NULL
;
5769 this->lwr
= ie
? ie
->lwr
: NULL
;
5771 upperIsInBounds
= false;
5772 lowerIsLessThanUpper
= false;
5776 SliceExp::SliceExp(Loc loc
, Expression
*e1
, Expression
*lwr
, Expression
*upr
)
5777 : UnaExp(loc
, TOKslice
, sizeof(SliceExp
), e1
)
5782 upperIsInBounds
= false;
5783 lowerIsLessThanUpper
= false;
5787 Expression
*SliceExp::syntaxCopy()
5789 SliceExp
*se
= new SliceExp(loc
, e1
->syntaxCopy(),
5790 lwr
? lwr
->syntaxCopy() : NULL
,
5791 upr
? upr
->syntaxCopy() : NULL
);
5792 se
->lengthVar
= this->lengthVar
; // bug7871
5796 int SliceExp::checkModifiable(Scope
*sc
, int flag
)
5798 //printf("SliceExp::checkModifiable %s\n", toChars());
5799 if (e1
->type
->ty
== Tsarray
||
5800 (e1
->op
== TOKindex
&& e1
->type
->ty
!= Tarray
) ||
5803 return e1
->checkModifiable(sc
, flag
);
5808 bool SliceExp::isLvalue()
5810 /* slice expression is rvalue in default, but
5811 * conversion to reference of static array is only allowed.
5813 return (type
&& type
->toBasetype()->ty
== Tsarray
);
5816 Expression
*SliceExp::toLvalue(Scope
*sc
, Expression
*e
)
5818 //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
5819 return (type
&& type
->toBasetype()->ty
== Tsarray
)
5820 ? this : Expression::toLvalue(sc
, e
);
5823 Expression
*SliceExp::modifiableLvalue(Scope
*, Expression
*)
5825 error("slice expression %s is not a modifiable lvalue", toChars());
5829 bool SliceExp::isBool(bool result
)
5831 return e1
->isBool(result
);
5834 /********************** ArrayLength **************************************/
5836 ArrayLengthExp::ArrayLengthExp(Loc loc
, Expression
*e1
)
5837 : UnaExp(loc
, TOKarraylength
, sizeof(ArrayLengthExp
), e1
)
5841 Expression
*opAssignToOp(Loc loc
, TOK op
, Expression
*e1
, Expression
*e2
)
5846 case TOKaddass
: e
= new AddExp(loc
, e1
, e2
); break;
5847 case TOKminass
: e
= new MinExp(loc
, e1
, e2
); break;
5848 case TOKmulass
: e
= new MulExp(loc
, e1
, e2
); break;
5849 case TOKdivass
: e
= new DivExp(loc
, e1
, e2
); break;
5850 case TOKmodass
: e
= new ModExp(loc
, e1
, e2
); break;
5851 case TOKandass
: e
= new AndExp(loc
, e1
, e2
); break;
5852 case TOKorass
: e
= new OrExp (loc
, e1
, e2
); break;
5853 case TOKxorass
: e
= new XorExp(loc
, e1
, e2
); break;
5854 case TOKshlass
: e
= new ShlExp(loc
, e1
, e2
); break;
5855 case TOKshrass
: e
= new ShrExp(loc
, e1
, e2
); break;
5856 case TOKushrass
: e
= new UshrExp(loc
, e1
, e2
); break;
5862 /*********************
5864 * array.length op= e2
5866 * array.length = array.length op e2
5868 * auto tmp = &array;
5869 * (*tmp).length = (*tmp).length op e2
5872 Expression
*ArrayLengthExp::rewriteOpAssign(BinExp
*exp
)
5876 assert(exp
->e1
->op
== TOKarraylength
);
5877 ArrayLengthExp
*ale
= (ArrayLengthExp
*)exp
->e1
;
5878 if (ale
->e1
->op
== TOKvar
)
5880 e
= opAssignToOp(exp
->loc
, exp
->op
, ale
, exp
->e2
);
5881 e
= new AssignExp(exp
->loc
, ale
->syntaxCopy(), e
);
5885 /* auto tmp = &array;
5886 * (*tmp).length = (*tmp).length op e2
5888 VarDeclaration
*tmp
= copyToTemp(0, "__arraylength", new AddrExp(ale
->loc
, ale
->e1
));
5890 Expression
*e1
= new ArrayLengthExp(ale
->loc
, new PtrExp(ale
->loc
, new VarExp(ale
->loc
, tmp
)));
5891 Expression
*elvalue
= e1
->syntaxCopy();
5892 e
= opAssignToOp(exp
->loc
, exp
->op
, e1
, exp
->e2
);
5893 e
= new AssignExp(exp
->loc
, elvalue
, e
);
5894 e
= new CommaExp(exp
->loc
, new DeclarationExp(ale
->loc
, tmp
), e
);
5899 /*********************** IntervalExp ********************************/
5901 // Mainly just a placeholder
5903 IntervalExp::IntervalExp(Loc loc
, Expression
*lwr
, Expression
*upr
)
5904 : Expression(loc
, TOKinterval
, sizeof(IntervalExp
))
5910 Expression
*IntervalExp::syntaxCopy()
5912 return new IntervalExp(loc
, lwr
->syntaxCopy(), upr
->syntaxCopy());
5915 /********************** DelegatePtrExp **************************************/
5917 DelegatePtrExp::DelegatePtrExp(Loc loc
, Expression
*e1
)
5918 : UnaExp(loc
, TOKdelegateptr
, sizeof(DelegatePtrExp
), e1
)
5922 bool DelegatePtrExp::isLvalue()
5924 return e1
->isLvalue();
5927 Expression
*DelegatePtrExp::toLvalue(Scope
*sc
, Expression
*e
)
5929 e1
= e1
->toLvalue(sc
, e
);
5933 Expression
*DelegatePtrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5935 if (sc
->func
->setUnsafe())
5937 error("cannot modify delegate pointer in @safe code %s", toChars());
5938 return new ErrorExp();
5940 return Expression::modifiableLvalue(sc
, e
);
5943 /********************** DelegateFuncptrExp **************************************/
5945 DelegateFuncptrExp::DelegateFuncptrExp(Loc loc
, Expression
*e1
)
5946 : UnaExp(loc
, TOKdelegatefuncptr
, sizeof(DelegateFuncptrExp
), e1
)
5950 bool DelegateFuncptrExp::isLvalue()
5952 return e1
->isLvalue();
5955 Expression
*DelegateFuncptrExp::toLvalue(Scope
*sc
, Expression
*e
)
5957 e1
= e1
->toLvalue(sc
, e
);
5961 Expression
*DelegateFuncptrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5963 if (sc
->func
->setUnsafe())
5965 error("cannot modify delegate function pointer in @safe code %s", toChars());
5966 return new ErrorExp();
5968 return Expression::modifiableLvalue(sc
, e
);
5971 /*********************** ArrayExp *************************************/
5973 // e1 [ i1, i2, i3, ... ]
5975 ArrayExp::ArrayExp(Loc loc
, Expression
*e1
, Expression
*index
)
5976 : UnaExp(loc
, TOKarray
, sizeof(ArrayExp
), e1
)
5978 arguments
= new Expressions();
5980 arguments
->push(index
);
5982 currentDimension
= 0;
5985 ArrayExp::ArrayExp(Loc loc
, Expression
*e1
, Expressions
*args
)
5986 : UnaExp(loc
, TOKarray
, sizeof(ArrayExp
), e1
)
5990 currentDimension
= 0;
5993 Expression
*ArrayExp::syntaxCopy()
5995 ArrayExp
*ae
= new ArrayExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
5996 ae
->lengthVar
= this->lengthVar
; // bug7871
6000 bool ArrayExp::isLvalue()
6002 if (type
&& type
->toBasetype()->ty
== Tvoid
)
6007 Expression
*ArrayExp::toLvalue(Scope
*, Expression
*)
6009 if (type
&& type
->toBasetype()->ty
== Tvoid
)
6010 error("voids have no value");
6014 /************************* DotExp ***********************************/
6016 DotExp::DotExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6017 : BinExp(loc
, TOKdot
, sizeof(DotExp
), e1
, e2
)
6021 /************************* CommaExp ***********************************/
6023 CommaExp::CommaExp(Loc loc
, Expression
*e1
, Expression
*e2
, bool generated
)
6024 : BinExp(loc
, TOKcomma
, sizeof(CommaExp
), e1
, e2
)
6026 isGenerated
= generated
;
6027 allowCommaExp
= generated
;
6030 bool CommaExp::isLvalue()
6032 return e2
->isLvalue();
6035 Expression
*CommaExp::toLvalue(Scope
*sc
, Expression
*)
6037 e2
= e2
->toLvalue(sc
, NULL
);
6041 int CommaExp::checkModifiable(Scope
*sc
, int flag
)
6043 return e2
->checkModifiable(sc
, flag
);
6046 Expression
*CommaExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6048 e2
= e2
->modifiableLvalue(sc
, e
);
6052 bool CommaExp::isBool(bool result
)
6054 return e2
->isBool(result
);
6057 Expression
*CommaExp::toBoolean(Scope
*sc
)
6059 Expression
*ex2
= e2
->toBoolean(sc
);
6060 if (ex2
->op
== TOKerror
)
6067 Expression
*CommaExp::addDtorHook(Scope
*sc
)
6069 e2
= e2
->addDtorHook(sc
);
6073 /************************** IndexExp **********************************/
6077 IndexExp::IndexExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6078 : BinExp(loc
, TOKindex
, sizeof(IndexExp
), e1
, e2
)
6080 //printf("IndexExp::IndexExp('%s')\n", toChars());
6082 modifiable
= false; // assume it is an rvalue
6083 indexIsInBounds
= false;
6086 Expression
*IndexExp::syntaxCopy()
6088 IndexExp
*ie
= new IndexExp(loc
, e1
->syntaxCopy(), e2
->syntaxCopy());
6089 ie
->lengthVar
= this->lengthVar
; // bug7871
6093 bool IndexExp::isLvalue()
6098 Expression
*IndexExp::toLvalue(Scope
*, Expression
*)
6103 int IndexExp::checkModifiable(Scope
*sc
, int flag
)
6105 if (e1
->type
->ty
== Tsarray
||
6106 e1
->type
->ty
== Taarray
||
6107 (e1
->op
== TOKindex
&& e1
->type
->ty
!= Tarray
) ||
6110 return e1
->checkModifiable(sc
, flag
);
6115 Expression
*IndexExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6117 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
6118 Expression
*ex
= markSettingAAElem();
6119 if (ex
->op
== TOKerror
)
6122 return Expression::modifiableLvalue(sc
, e
);
6125 Expression
*IndexExp::markSettingAAElem()
6127 if (e1
->type
->toBasetype()->ty
== Taarray
)
6129 Type
*t2b
= e2
->type
->toBasetype();
6130 if (t2b
->ty
== Tarray
&& t2b
->nextOf()->isMutable())
6132 error("associative arrays can only be assigned values with immutable keys, not %s", e2
->type
->toChars());
6133 return new ErrorExp();
6137 if (e1
->op
== TOKindex
)
6139 Expression
*ex
= ((IndexExp
*)e1
)->markSettingAAElem();
6140 if (ex
->op
== TOKerror
)
6148 /************************* PostExp ***********************************/
6150 PostExp::PostExp(TOK op
, Loc loc
, Expression
*e
)
6151 : BinExp(loc
, op
, sizeof(PostExp
), e
,
6152 new IntegerExp(loc
, 1, Type::tint32
))
6156 /************************* PreExp ***********************************/
6158 PreExp::PreExp(TOK op
, Loc loc
, Expression
*e
)
6159 : UnaExp(loc
, op
, sizeof(PreExp
), e
)
6163 /************************************************************/
6165 /* op can be TOKassign, TOKconstruct, or TOKblit */
6167 AssignExp::AssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6168 : BinExp(loc
, TOKassign
, sizeof(AssignExp
), e1
, e2
)
6173 bool AssignExp::isLvalue()
6175 // Array-op 'x[] = y[]' should make an rvalue.
6176 // Setting array length 'x.length = v' should make an rvalue.
6177 if (e1
->op
== TOKslice
||
6178 e1
->op
== TOKarraylength
)
6185 Expression
*AssignExp::toLvalue(Scope
*sc
, Expression
*ex
)
6187 if (e1
->op
== TOKslice
||
6188 e1
->op
== TOKarraylength
)
6190 return Expression::toLvalue(sc
, ex
);
6193 /* In front-end level, AssignExp should make an lvalue of e1.
6194 * Taking the address of e1 will be handled in low level layer,
6195 * so this function does nothing.
6200 Expression
*AssignExp::toBoolean(Scope
*)
6204 // are usually mistakes.
6206 error("assignment cannot be used as a condition, perhaps == was meant?");
6207 return new ErrorExp();
6210 /************************************************************/
6212 ConstructExp::ConstructExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6213 : AssignExp(loc
, e1
, e2
)
6218 ConstructExp::ConstructExp(Loc loc
, VarDeclaration
*v
, Expression
*e2
)
6219 : AssignExp(loc
, new VarExp(loc
, v
), e2
)
6221 assert(v
->type
&& e1
->type
);
6224 if (v
->storage_class
& (STCref
| STCout
))
6225 memset
|= referenceInit
;
6228 /************************************************************/
6230 BlitExp::BlitExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6231 : AssignExp(loc
, e1
, e2
)
6236 BlitExp::BlitExp(Loc loc
, VarDeclaration
*v
, Expression
*e2
)
6237 : AssignExp(loc
, new VarExp(loc
, v
), e2
)
6239 assert(v
->type
&& e1
->type
);
6242 if (v
->storage_class
& (STCref
| STCout
))
6243 memset
|= referenceInit
;
6246 /************************************************************/
6248 AddAssignExp::AddAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6249 : BinAssignExp(loc
, TOKaddass
, sizeof(AddAssignExp
), e1
, e2
)
6253 /************************************************************/
6255 MinAssignExp::MinAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6256 : BinAssignExp(loc
, TOKminass
, sizeof(MinAssignExp
), e1
, e2
)
6260 /************************************************************/
6262 CatAssignExp::CatAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6263 : BinAssignExp(loc
, TOKcatass
, sizeof(CatAssignExp
), e1
, e2
)
6267 /************************************************************/
6269 MulAssignExp::MulAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6270 : BinAssignExp(loc
, TOKmulass
, sizeof(MulAssignExp
), e1
, e2
)
6274 /************************************************************/
6276 DivAssignExp::DivAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6277 : BinAssignExp(loc
, TOKdivass
, sizeof(DivAssignExp
), e1
, e2
)
6281 /************************************************************/
6283 ModAssignExp::ModAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6284 : BinAssignExp(loc
, TOKmodass
, sizeof(ModAssignExp
), e1
, e2
)
6288 /************************************************************/
6290 ShlAssignExp::ShlAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6291 : BinAssignExp(loc
, TOKshlass
, sizeof(ShlAssignExp
), e1
, e2
)
6295 /************************************************************/
6297 ShrAssignExp::ShrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6298 : BinAssignExp(loc
, TOKshrass
, sizeof(ShrAssignExp
), e1
, e2
)
6302 /************************************************************/
6304 UshrAssignExp::UshrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6305 : BinAssignExp(loc
, TOKushrass
, sizeof(UshrAssignExp
), e1
, e2
)
6309 /************************************************************/
6311 AndAssignExp::AndAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6312 : BinAssignExp(loc
, TOKandass
, sizeof(AndAssignExp
), e1
, e2
)
6316 /************************************************************/
6318 OrAssignExp::OrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6319 : BinAssignExp(loc
, TOKorass
, sizeof(OrAssignExp
), e1
, e2
)
6323 /************************************************************/
6325 XorAssignExp::XorAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6326 : BinAssignExp(loc
, TOKxorass
, sizeof(XorAssignExp
), e1
, e2
)
6330 /***************** PowAssignExp *******************************************/
6332 PowAssignExp::PowAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6333 : BinAssignExp(loc
, TOKpowass
, sizeof(PowAssignExp
), e1
, e2
)
6337 /************************* AddExp *****************************/
6339 AddExp::AddExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6340 : BinExp(loc
, TOKadd
, sizeof(AddExp
), e1
, e2
)
6344 /************************************************************/
6346 MinExp::MinExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6347 : BinExp(loc
, TOKmin
, sizeof(MinExp
), e1
, e2
)
6351 /************************* CatExp *****************************/
6353 CatExp::CatExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6354 : BinExp(loc
, TOKcat
, sizeof(CatExp
), e1
, e2
)
6358 /************************************************************/
6360 MulExp::MulExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6361 : BinExp(loc
, TOKmul
, sizeof(MulExp
), e1
, e2
)
6365 /************************************************************/
6367 DivExp::DivExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6368 : BinExp(loc
, TOKdiv
, sizeof(DivExp
), e1
, e2
)
6372 /************************************************************/
6374 ModExp::ModExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6375 : BinExp(loc
, TOKmod
, sizeof(ModExp
), e1
, e2
)
6379 /************************************************************/
6381 PowExp::PowExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6382 : BinExp(loc
, TOKpow
, sizeof(PowExp
), e1
, e2
)
6386 /************************************************************/
6388 ShlExp::ShlExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6389 : BinExp(loc
, TOKshl
, sizeof(ShlExp
), e1
, e2
)
6393 /************************************************************/
6395 ShrExp::ShrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6396 : BinExp(loc
, TOKshr
, sizeof(ShrExp
), e1
, e2
)
6400 /************************************************************/
6402 UshrExp::UshrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6403 : BinExp(loc
, TOKushr
, sizeof(UshrExp
), e1
, e2
)
6407 /************************************************************/
6409 AndExp::AndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6410 : BinExp(loc
, TOKand
, sizeof(AndExp
), e1
, e2
)
6414 /************************************************************/
6416 OrExp::OrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6417 : BinExp(loc
, TOKor
, sizeof(OrExp
), e1
, e2
)
6421 /************************************************************/
6423 XorExp::XorExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6424 : BinExp(loc
, TOKxor
, sizeof(XorExp
), e1
, e2
)
6428 /************************************************************/
6430 OrOrExp::OrOrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6431 : BinExp(loc
, TOKoror
, sizeof(OrOrExp
), e1
, e2
)
6435 Expression
*OrOrExp::toBoolean(Scope
*sc
)
6437 Expression
*ex2
= e2
->toBoolean(sc
);
6438 if (ex2
->op
== TOKerror
)
6444 /************************************************************/
6446 AndAndExp::AndAndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6447 : BinExp(loc
, TOKandand
, sizeof(AndAndExp
), e1
, e2
)
6451 Expression
*AndAndExp::toBoolean(Scope
*sc
)
6453 Expression
*ex2
= e2
->toBoolean(sc
);
6454 if (ex2
->op
== TOKerror
)
6460 /************************************************************/
6462 InExp::InExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6463 : BinExp(loc
, TOKin
, sizeof(InExp
), e1
, e2
)
6467 /************************************************************/
6469 /* This deletes the key e1 from the associative array e2
6472 RemoveExp::RemoveExp(Loc loc
, Expression
*e1
, Expression
*e2
)
6473 : BinExp(loc
, TOKremove
, sizeof(RemoveExp
), e1
, e2
)
6478 /************************************************************/
6480 CmpExp::CmpExp(TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
6481 : BinExp(loc
, op
, sizeof(CmpExp
), e1
, e2
)
6485 /************************************************************/
6487 EqualExp::EqualExp(TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
6488 : BinExp(loc
, op
, sizeof(EqualExp
), e1
, e2
)
6490 assert(op
== TOKequal
|| op
== TOKnotequal
);
6493 /************************************************************/
6495 IdentityExp::IdentityExp(TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
6496 : BinExp(loc
, op
, sizeof(IdentityExp
), e1
, e2
)
6500 /****************************************************************/
6502 CondExp::CondExp(Loc loc
, Expression
*econd
, Expression
*e1
, Expression
*e2
)
6503 : BinExp(loc
, TOKquestion
, sizeof(CondExp
), e1
, e2
)
6505 this->econd
= econd
;
6508 Expression
*CondExp::syntaxCopy()
6510 return new CondExp(loc
, econd
->syntaxCopy(), e1
->syntaxCopy(), e2
->syntaxCopy());
6513 void CondExp::hookDtors(Scope
*sc
)
6515 class DtorVisitor
: public StoppableVisitor
6520 VarDeclaration
*vcond
;
6523 DtorVisitor(Scope
*sc
, CondExp
*ce
)
6530 void visit(Expression
*)
6532 //printf("(e = %s)\n", e->toChars());
6535 void visit(DeclarationExp
*e
)
6537 VarDeclaration
*v
= e
->declaration
->isVarDeclaration();
6538 if (v
&& !v
->isDataseg())
6542 ExpInitializer
*ei
= v
->_init
->isExpInitializer();
6544 ei
->exp
->accept(this);
6547 if (v
->needsScopeDtor())
6551 vcond
= copyToTemp(STCvolatile
, "__cond", ce
->econd
);
6552 vcond
->semantic(sc
);
6554 Expression
*de
= new DeclarationExp(ce
->econd
->loc
, vcond
);
6555 de
= semantic(de
, sc
);
6557 Expression
*ve
= new VarExp(ce
->econd
->loc
, vcond
);
6558 ce
->econd
= Expression::combine(de
, ve
);
6561 //printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6562 Expression
*ve
= new VarExp(vcond
->loc
, vcond
);
6564 v
->edtor
= new AndAndExp(v
->edtor
->loc
, ve
, v
->edtor
);
6566 v
->edtor
= new OrOrExp(v
->edtor
->loc
, ve
, v
->edtor
);
6567 v
->edtor
= semantic(v
->edtor
, sc
);
6568 //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6574 DtorVisitor
v(sc
, this);
6575 //printf("+%s\n", toChars());
6576 v
.isThen
= true; walkPostorder(e1
, &v
);
6577 v
.isThen
= false; walkPostorder(e2
, &v
);
6578 //printf("-%s\n", toChars());
6581 bool CondExp::isLvalue()
6583 return e1
->isLvalue() && e2
->isLvalue();
6587 Expression
*CondExp::toLvalue(Scope
*sc
, Expression
*)
6589 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
6590 CondExp
*e
= (CondExp
*)copy();
6591 e
->e1
= e1
->toLvalue(sc
, NULL
)->addressOf();
6592 e
->e2
= e2
->toLvalue(sc
, NULL
)->addressOf();
6593 e
->type
= type
->pointerTo();
6594 return new PtrExp(loc
, e
, type
);
6597 int CondExp::checkModifiable(Scope
*sc
, int flag
)
6599 return e1
->checkModifiable(sc
, flag
) && e2
->checkModifiable(sc
, flag
);
6602 Expression
*CondExp::modifiableLvalue(Scope
*sc
, Expression
*)
6604 //error("conditional expression %s is not a modifiable lvalue", toChars());
6605 e1
= e1
->modifiableLvalue(sc
, e1
);
6606 e2
= e2
->modifiableLvalue(sc
, e2
);
6607 return toLvalue(sc
, this);
6610 Expression
*CondExp::toBoolean(Scope
*sc
)
6612 Expression
*ex1
= e1
->toBoolean(sc
);
6613 Expression
*ex2
= e2
->toBoolean(sc
);
6614 if (ex1
->op
== TOKerror
)
6616 if (ex2
->op
== TOKerror
)
6623 /****************************************************************/
6625 DefaultInitExp::DefaultInitExp(Loc loc
, TOK subop
, int size
)
6626 : Expression(loc
, TOKdefault
, size
)
6628 this->subop
= subop
;
6631 /****************************************************************/
6633 FileInitExp::FileInitExp(Loc loc
, TOK tok
)
6634 : DefaultInitExp(loc
, tok
, sizeof(FileInitExp
))
6638 Expression
*FileInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6640 //printf("FileInitExp::resolve() %s\n", toChars());
6641 const char *s
= loc
.filename
? loc
.filename
: sc
->_module
->ident
->toChars();
6642 if (subop
== TOKfilefullpath
)
6643 s
= FileName::combine(sc
->_module
->srcfilePath
, s
);
6644 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6645 e
= semantic(e
, sc
);
6646 e
= e
->castTo(sc
, type
);
6650 /****************************************************************/
6652 LineInitExp::LineInitExp(Loc loc
)
6653 : DefaultInitExp(loc
, TOKline
, sizeof(LineInitExp
))
6657 Expression
*LineInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6659 Expression
*e
= new IntegerExp(loc
, loc
.linnum
, Type::tint32
);
6660 e
= e
->castTo(sc
, type
);
6664 /****************************************************************/
6666 ModuleInitExp::ModuleInitExp(Loc loc
)
6667 : DefaultInitExp(loc
, TOKmodulestring
, sizeof(ModuleInitExp
))
6671 Expression
*ModuleInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6675 s
= sc
->callsc
->_module
->toPrettyChars();
6677 s
= sc
->_module
->toPrettyChars();
6678 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6679 e
= semantic(e
, sc
);
6680 e
= e
->castTo(sc
, type
);
6684 /****************************************************************/
6686 FuncInitExp::FuncInitExp(Loc loc
)
6687 : DefaultInitExp(loc
, TOKfuncstring
, sizeof(FuncInitExp
))
6691 Expression
*FuncInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6694 if (sc
->callsc
&& sc
->callsc
->func
)
6695 s
= sc
->callsc
->func
->Dsymbol::toPrettyChars();
6697 s
= sc
->func
->Dsymbol::toPrettyChars();
6700 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6701 e
= semantic(e
, sc
);
6702 e
= e
->castTo(sc
, type
);
6706 /****************************************************************/
6708 PrettyFuncInitExp::PrettyFuncInitExp(Loc loc
)
6709 : DefaultInitExp(loc
, TOKprettyfunc
, sizeof(PrettyFuncInitExp
))
6713 Expression
*PrettyFuncInitExp::resolveLoc(Loc loc
, Scope
*sc
)
6715 FuncDeclaration
*fd
;
6716 if (sc
->callsc
&& sc
->callsc
->func
)
6717 fd
= sc
->callsc
->func
;
6724 const char *funcStr
= fd
->Dsymbol::toPrettyChars();
6726 functionToBufferWithIdent((TypeFunction
*)fd
->type
, &buf
, funcStr
);
6727 s
= buf
.extractString();
6734 Expression
*e
= new StringExp(loc
, const_cast<char *>(s
));
6735 e
= semantic(e
, sc
);
6736 e
= e
->castTo(sc
, type
);
6740 /****************************************************************/
6742 Expression
*extractOpDollarSideEffect(Scope
*sc
, UnaExp
*ue
)
6745 Expression
*e1
= Expression::extractLast(ue
->e1
, &e0
);
6746 // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
6748 if (!isTrivialExp(e1
))
6750 /* Even if opDollar is needed, 'e1' should be evaluate only once. So
6752 * e1.opIndex( ... use of $ ... )
6753 * e1.opSlice( ... use of $ ... )
6755 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
6756 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
6758 e1
= extractSideEffect(sc
, "__dop", &e0
, e1
, false);
6759 assert(e1
->op
== TOKvar
);
6760 VarExp
*ve
= (VarExp
*)e1
;
6761 ve
->var
->storage_class
|= STCexptemp
; // lifetime limited to expression
6767 /**************************************
6768 * Runs semantic on ae->arguments. Declares temporary variables
6771 Expression
*resolveOpDollar(Scope
*sc
, ArrayExp
*ae
, Expression
**pe0
)
6773 assert(!ae
->lengthVar
);
6777 AggregateDeclaration
*ad
= isAggregate(ae
->e1
->type
);
6778 Dsymbol
*slice
= search_function(ad
, Id::slice
);
6779 //printf("slice = %s %s\n", slice->kind(), slice->toChars());
6781 for (size_t i
= 0; i
< ae
->arguments
->dim
; i
++)
6784 *pe0
= extractOpDollarSideEffect(sc
, ae
);
6786 Expression
*e
= (*ae
->arguments
)[i
];
6787 if (e
->op
== TOKinterval
&& !(slice
&& slice
->isTemplateDeclaration()))
6790 if (ae
->arguments
->dim
== 1)
6792 ae
->error("multi-dimensional slicing requires template opSlice");
6793 return new ErrorExp();
6795 //printf("[%d] e = %s\n", i, e->toChars());
6797 // Create scope for '$' variable for this dimension
6798 ArrayScopeSymbol
*sym
= new ArrayScopeSymbol(sc
, ae
);
6800 sym
->parent
= sc
->scopesym
;
6802 ae
->lengthVar
= NULL
; // Create it only if required
6803 ae
->currentDimension
= i
; // Dimension for $, if required
6805 e
= semantic(e
, sc
);
6806 e
= resolveProperties(sc
, e
);
6808 if (ae
->lengthVar
&& sc
->func
)
6810 // If $ was used, declare it now
6811 Expression
*de
= new DeclarationExp(ae
->loc
, ae
->lengthVar
);
6812 de
= semantic(de
, sc
);
6813 *pe0
= Expression::combine(*pe0
, de
);
6817 if (e
->op
== TOKinterval
)
6819 IntervalExp
*ie
= (IntervalExp
*)e
;
6821 Objects
*tiargs
= new Objects();
6822 Expression
*edim
= new IntegerExp(ae
->loc
, i
, Type::tsize_t
);
6823 edim
= semantic(edim
, sc
);
6826 Expressions
*fargs
= new Expressions();
6827 fargs
->push(ie
->lwr
);
6828 fargs
->push(ie
->upr
);
6830 unsigned xerrors
= global
.startGagging();
6832 FuncDeclaration
*fslice
= resolveFuncCall(ae
->loc
, sc
, slice
, tiargs
, ae
->e1
->type
, fargs
, 1);
6834 global
.endGagging(xerrors
);
6838 e
= new DotTemplateInstanceExp(ae
->loc
, ae
->e1
, slice
->ident
, tiargs
);
6839 e
= new CallExp(ae
->loc
, e
, fargs
);
6840 e
= semantic(e
, sc
);
6845 ae
->error("%s has no value", e
->toChars());
6848 if (e
->op
== TOKerror
)
6851 (*ae
->arguments
)[i
] = e
;
6857 /**************************************
6858 * Runs semantic on se->lwr and se->upr. Declares a temporary variable
6861 Expression
*resolveOpDollar(Scope
*sc
, ArrayExp
*ae
, IntervalExp
*ie
, Expression
**pe0
)
6863 //assert(!ae->lengthVar);
6867 VarDeclaration
*lengthVar
= ae
->lengthVar
;
6869 // create scope for '$'
6870 ArrayScopeSymbol
*sym
= new ArrayScopeSymbol(sc
, ae
);
6872 sym
->parent
= sc
->scopesym
;
6875 for (size_t i
= 0; i
< 2; ++i
)
6877 Expression
*e
= i
== 0 ? ie
->lwr
: ie
->upr
;
6878 e
= semantic(e
, sc
);
6879 e
= resolveProperties(sc
, e
);
6882 ae
->error("%s has no value", e
->toChars());
6883 return new ErrorExp();
6885 (i
== 0 ? ie
->lwr
: ie
->upr
) = e
;
6888 if (lengthVar
!= ae
->lengthVar
&& sc
->func
)
6890 // If $ was used, declare it now
6891 Expression
*de
= new DeclarationExp(ae
->loc
, ae
->lengthVar
);
6892 de
= semantic(de
, sc
);
6893 *pe0
= Expression::combine(*pe0
, de
);
6900 Expression
*BinExp::reorderSettingAAElem(Scope
*sc
)
6904 if (be
->e1
->op
!= TOKindex
)
6906 IndexExp
*ie
= (IndexExp
*)be
->e1
;
6907 if (ie
->e1
->type
->toBasetype()->ty
!= Taarray
)
6910 /* Fix evaluation order of setting AA element. (Bugzilla 3825)
6912 * aa[k1][k2][k3] op= val;
6914 * auto ref __aatmp = aa;
6915 * auto ref __aakey3 = k1, __aakey2 = k2, __aakey1 = k3;
6916 * auto ref __aaval = val;
6917 * __aatmp[__aakey3][__aakey2][__aakey1] op= __aaval; // assignment
6920 Expression
*e0
= NULL
;
6923 Expression
*de
= NULL
;
6924 ie
->e2
= extractSideEffect(sc
, "__aakey", &de
, ie
->e2
);
6925 e0
= Expression::combine(de
, e0
);
6927 Expression
*ie1
= ie
->e1
;
6928 if (ie1
->op
!= TOKindex
||
6929 ((IndexExp
*)ie1
)->e1
->type
->toBasetype()->ty
!= Taarray
)
6933 ie
= (IndexExp
*)ie1
;
6935 assert(ie
->e1
->type
->toBasetype()->ty
== Taarray
);
6937 Expression
*de
= NULL
;
6938 ie
->e1
= extractSideEffect(sc
, "__aatmp", &de
, ie
->e1
);
6939 e0
= Expression::combine(de
, e0
);
6941 be
->e2
= extractSideEffect(sc
, "__aaval", &e0
, be
->e2
, true);
6943 //printf("-e0 = %s, be = %s\n", e0->toChars(), be->toChars());
6944 return Expression::combine(e0
, be
);