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
10 #include "root/dsystem.h"
11 #include "root/rmem.h"
12 #include "root/checkedint.h"
15 #include "statement.h"
16 #include "expression.h"
19 #include "staticassert.h"
22 #include "declaration.h"
23 #include "aggregate.h"
31 StorageClass
mergeFuncAttrs(StorageClass s1
, FuncDeclaration
*f
);
32 bool checkReturnEscapeRef(Scope
*sc
, Expression
*e
, bool gag
);
33 bool checkThrowEscape(Scope
*sc
, Expression
*e
, bool gag
);
34 LabelStatement
*checkLabeledLoop(Scope
*sc
, Statement
*statement
);
35 Identifier
*fixupLabelName(Scope
*sc
, Identifier
*ident
);
36 FuncDeclaration
*isFuncAddress(Expression
*e
, bool *hasOverloads
= NULL
);
37 VarDeclaration
*copyToTemp(StorageClass stc
, const char *name
, Expression
*e
);
38 Expression
*checkAssignmentAsCondition(Expression
*e
);
39 TypeIdentifier
*getThrowable();
41 Expression
*semantic(Expression
*e
, Scope
*sc
);
42 Statement
*semantic(Statement
*s
, Scope
*sc
);
43 void semantic(Catch
*c
, Scope
*sc
);
44 Statement
*semanticNoScope(Statement
*s
, Scope
*sc
);
45 Statement
*semanticScope(Statement
*s
, Scope
*sc
, Statement
*sbreak
, Statement
*scontinue
);
46 int blockExit(Statement
*s
, FuncDeclaration
*func
, bool mustNotThrow
);
48 class StatementSemanticVisitor
: public Visitor
54 StatementSemanticVisitor(Scope
*sc
)
63 result
= new ErrorStatement();
67 void visit(Statement
*s
)
72 void visit(ErrorStatement
*s
)
77 void visit(PeelStatement
*s
)
79 /* "peel" off this wrapper, and don't run semantic()
85 void visit(ExpStatement
*s
)
89 //printf("ExpStatement::semantic() %s\n", s->exp->toChars());
91 // Allow CommaExp in ExpStatement because return isn't used
92 if (s
->exp
->op
== TOKcomma
)
93 ((CommaExp
*)s
->exp
)->allowCommaExp
= true;
95 s
->exp
= semantic(s
->exp
, sc
);
96 s
->exp
= resolveProperties(sc
, s
->exp
);
97 s
->exp
= s
->exp
->addDtorHook(sc
);
98 if (FuncDeclaration
*f
= isFuncAddress(s
->exp
))
100 if (f
->checkForwardRef(s
->exp
->loc
))
101 s
->exp
= new ErrorExp();
103 if (discardValue(s
->exp
))
104 s
->exp
= new ErrorExp();
106 s
->exp
= s
->exp
->optimize(WANTvalue
);
107 s
->exp
= checkGC(sc
, s
->exp
);
108 if (s
->exp
->op
== TOKerror
)
114 void visit(CompileStatement
*cs
)
116 //printf("CompileStatement::semantic() %s\n", cs->exp->toChars());
117 Statements
*a
= cs
->flatten(sc
);
120 Statement
*s
= new CompoundStatement(cs
->loc
, a
);
121 result
= semantic(s
, sc
);
124 void visit(CompoundStatement
*cs
)
126 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", cs, sc);
127 for (size_t i
= 0; i
< cs
->statements
->dim
; )
129 Statement
*s
= (*cs
->statements
)[i
];
132 Statements
*flt
= s
->flatten(sc
);
135 cs
->statements
->remove(i
);
136 cs
->statements
->insert(i
, flt
);
140 (*cs
->statements
)[i
] = s
;
144 Statement
*sexception
;
147 (*cs
->statements
)[i
] = s
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
150 sentry
= semantic(sentry
, sc
);
151 cs
->statements
->insert(i
, sentry
);
155 sexception
= semantic(sexception
, sc
);
158 if (i
+ 1 == cs
->statements
->dim
&& !sfinally
)
168 * catch (Throwable __o)
169 * { sexception; throw __o; }
171 Statements
*a
= new Statements();
172 for (size_t j
= i
+ 1; j
< cs
->statements
->dim
; j
++)
174 a
->push((*cs
->statements
)[j
]);
176 Statement
*body
= new CompoundStatement(Loc(), a
);
177 body
= new ScopeStatement(Loc(), body
, Loc());
179 Identifier
*id
= Identifier::generateId("__o");
181 Statement
*handler
= new PeelStatement(sexception
);
182 if (blockExit(sexception
, sc
->func
, false) & BEfallthru
)
184 ThrowStatement
*ts
= new ThrowStatement(Loc(), new IdentifierExp(Loc(), id
));
185 ts
->internalThrow
= true;
186 handler
= new CompoundStatement(Loc(), handler
, ts
);
189 Catches
*catches
= new Catches();
190 Catch
*ctch
= new Catch(Loc(), getThrowable(), id
, handler
);
191 ctch
->internalCatch
= true;
194 s
= new TryCatchStatement(Loc(), body
, catches
);
196 s
= new TryFinallyStatement(Loc(), s
, sfinally
);
199 cs
->statements
->setDim(i
+ 1);
200 cs
->statements
->push(s
);
206 if (0 && i
+ 1 == cs
->statements
->dim
)
208 cs
->statements
->push(sfinally
);
215 * s; try { s1; s2; } finally { sfinally; }
217 Statements
*a
= new Statements();
218 for (size_t j
= i
+ 1; j
< cs
->statements
->dim
; j
++)
220 a
->push((*cs
->statements
)[j
]);
222 Statement
*body
= new CompoundStatement(Loc(), a
);
223 s
= new TryFinallyStatement(Loc(), body
, sfinally
);
225 cs
->statements
->setDim(i
+ 1);
226 cs
->statements
->push(s
);
233 /* Remove NULL statements from the list.
235 cs
->statements
->remove(i
);
241 for (size_t i
= 0; i
< cs
->statements
->dim
; ++i
)
244 Statement
*s
= (*cs
->statements
)[i
];
248 Statement
*se
= s
->isErrorStatement();
255 /* Bugzilla 11653: 'semantic' may return another CompoundStatement
256 * (eg. CaseRangeStatement), so flatten it here.
258 Statements
*flt
= s
->flatten(sc
);
261 cs
->statements
->remove(i
);
262 cs
->statements
->insert(i
, flt
);
263 if (cs
->statements
->dim
<= i
)
268 if (cs
->statements
->dim
== 1)
270 result
= (*cs
->statements
)[0];
276 void visit(UnrolledLoopStatement
*uls
)
278 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", uls, sc);
279 Scope
*scd
= sc
->push();
281 scd
->scontinue
= uls
;
283 Statement
*serror
= NULL
;
284 for (size_t i
= 0; i
< uls
->statements
->dim
; i
++)
286 Statement
*s
= (*uls
->statements
)[i
];
289 //printf("[%d]: %s\n", i, s->toChars());
290 s
= semantic(s
, scd
);
291 (*uls
->statements
)[i
] = s
;
294 serror
= s
->isErrorStatement();
299 result
= serror
? serror
: uls
;
302 void visit(ScopeStatement
*ss
)
305 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
308 sym
= new ScopeDsymbol();
309 sym
->parent
= sc
->scopesym
;
310 sym
->endlinnum
= ss
->endloc
.linnum
;
313 Statements
*a
= ss
->statement
->flatten(sc
);
316 ss
->statement
= new CompoundStatement(ss
->loc
, a
);
319 ss
->statement
= semantic(ss
->statement
, sc
);
322 if (ss
->statement
->isErrorStatement())
325 result
= ss
->statement
;
330 Statement
*sexception
;
333 ss
->statement
= ss
->statement
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
338 //printf("adding sfinally\n");
339 sfinally
= semantic(sfinally
, sc
);
340 ss
->statement
= new CompoundStatement(ss
->loc
, ss
->statement
, sfinally
);
349 void visit(WhileStatement
*ws
)
351 /* Rewrite as a for(;condition;) loop
353 Statement
*s
= new ForStatement(ws
->loc
, NULL
, ws
->condition
, NULL
, ws
->_body
, ws
->endloc
);
358 void visit(DoStatement
*ds
)
362 ds
->_body
= semanticScope(ds
->_body
, sc
, ds
, ds
);
365 if (ds
->condition
->op
== TOKdotid
)
366 ((DotIdExp
*)ds
->condition
)->noderef
= true;
368 // check in syntax level
369 ds
->condition
= checkAssignmentAsCondition(ds
->condition
);
371 ds
->condition
= semantic(ds
->condition
, sc
);
372 ds
->condition
= resolveProperties(sc
, ds
->condition
);
373 ds
->condition
= ds
->condition
->optimize(WANTvalue
);
374 ds
->condition
= checkGC(sc
, ds
->condition
);
376 ds
->condition
= ds
->condition
->toBoolean(sc
);
378 if (ds
->condition
->op
== TOKerror
)
381 if (ds
->_body
&& ds
->_body
->isErrorStatement())
390 void visit(ForStatement
*fs
)
392 //printf("ForStatement::semantic %s\n", toChars());
397 * for (auto v1 = i1, v2 = i2; condition; increment) { ... }
399 * { auto v1 = i1, v2 = i2; for (; condition; increment) { ... } }
405 * for (; condition; increment) { ... }
406 * } finally { v2.~this(); }
407 * } finally { v1.~this(); }
409 Statements
*ainit
= new Statements();
410 ainit
->push(fs
->_init
);
413 Statement
*s
= new CompoundStatement(fs
->loc
, ainit
);
414 s
= new ScopeStatement(fs
->loc
, s
, fs
->endloc
);
416 if (!s
->isErrorStatement())
418 if (LabelStatement
*ls
= checkLabeledLoop(sc
, fs
))
420 fs
->relatedLabeled
= s
;
425 assert(fs
->_init
== NULL
);
427 ScopeDsymbol
*sym
= new ScopeDsymbol();
428 sym
->parent
= sc
->scopesym
;
429 sym
->endlinnum
= fs
->endloc
.linnum
;
435 if (fs
->condition
->op
== TOKdotid
)
436 ((DotIdExp
*)fs
->condition
)->noderef
= true;
438 // check in syntax level
439 fs
->condition
= checkAssignmentAsCondition(fs
->condition
);
441 fs
->condition
= semantic(fs
->condition
, sc
);
442 fs
->condition
= resolveProperties(sc
, fs
->condition
);
443 fs
->condition
= fs
->condition
->optimize(WANTvalue
);
444 fs
->condition
= checkGC(sc
, fs
->condition
);
445 fs
->condition
= fs
->condition
->toBoolean(sc
);
449 if (fs
->increment
->op
== TOKcomma
)
450 ((CommaExp
*)fs
->increment
)->allowCommaExp
= true;
451 fs
->increment
= semantic(fs
->increment
, sc
);
452 fs
->increment
= resolveProperties(sc
, fs
->increment
);
453 fs
->increment
= fs
->increment
->optimize(WANTvalue
);
454 fs
->increment
= checkGC(sc
, fs
->increment
);
460 fs
->_body
= semanticNoScope(fs
->_body
, sc
);
465 if ((fs
->condition
&& fs
->condition
->op
== TOKerror
) ||
466 (fs
->increment
&& fs
->increment
->op
== TOKerror
) ||
467 (fs
->_body
&& fs
->_body
->isErrorStatement()))
473 void visit(ForeachStatement
*fs
)
475 //printf("ForeachStatement::semantic() %p\n", fs);
479 size_t dim
= fs
->parameters
->dim
;
480 TypeAArray
*taa
= NULL
;
481 Dsymbol
*sapply
= NULL
;
488 fs
->func
= fs
->func
->fes
->func
;
490 VarDeclaration
*vinit
= NULL
;
491 fs
->aggr
= semantic(fs
->aggr
, sc
);
492 fs
->aggr
= resolveProperties(sc
, fs
->aggr
);
493 fs
->aggr
= fs
->aggr
->optimize(WANTvalue
);
494 if (fs
->aggr
->op
== TOKerror
)
497 Expression
*oaggr
= fs
->aggr
;
498 if (fs
->aggr
->type
&& fs
->aggr
->type
->toBasetype()->ty
== Tstruct
&&
499 ((TypeStruct
*)(fs
->aggr
->type
->toBasetype()))->sym
->dtor
&&
500 fs
->aggr
->op
!= TOKtype
&& !fs
->aggr
->isLvalue())
502 // Bugzilla 14653: Extend the life of rvalue aggregate till the end of foreach.
503 vinit
= copyToTemp(STCrvalue
, "__aggr", fs
->aggr
);
505 fs
->aggr
= new VarExp(fs
->aggr
->loc
, vinit
);
508 if (!inferAggregate(fs
, sc
, sapply
))
510 const char *msg
= "";
511 if (fs
->aggr
->type
&& isAggregate(fs
->aggr
->type
))
513 msg
= ", define opApply(), range primitives, or use .tupleof";
515 fs
->error("invalid foreach aggregate %s%s", oaggr
->toChars(), msg
);
519 Dsymbol
* sapplyOld
= sapply
; // 'sapply' will be NULL if and after 'inferApplyArgTypes' errors
521 /* Check for inference errors
523 if (!inferApplyArgTypes(fs
, sc
, sapply
))
526 Try and extract the parameter count of the opApply callback function, e.g.:
527 int opApply(int delegate(int, float)) => 2 args
529 bool foundMismatch
= false;
530 size_t foreachParamCount
= 0;
533 if (FuncDeclaration
*fd
= sapplyOld
->isFuncDeclaration())
535 int fvarargs
; // ignored (opApply shouldn't take variadics)
536 Parameters
*fparameters
= fd
->getParameters(&fvarargs
);
538 if (Parameter::dim(fparameters
) == 1)
540 // first param should be the callback function
541 Parameter
*fparam
= Parameter::getNth(fparameters
, 0);
542 if ((fparam
->type
->ty
== Tpointer
|| fparam
->type
->ty
== Tdelegate
) &&
543 fparam
->type
->nextOf()->ty
== Tfunction
)
545 TypeFunction
*tf
= (TypeFunction
*)fparam
->type
->nextOf();
546 foreachParamCount
= Parameter::dim(tf
->parameters
);
547 foundMismatch
= true;
553 //printf("dim = %d, parameters->dim = %d\n", dim, fs->parameters->dim);
554 if (foundMismatch
&& dim
!= foreachParamCount
)
556 const char *plural
= foreachParamCount
> 1 ? "s" : "";
557 fs
->error("cannot infer argument types, expected %d argument%s, not %d",
558 foreachParamCount
, plural
, dim
);
561 fs
->error("cannot uniquely infer foreach argument types");
566 Type
*tab
= fs
->aggr
->type
->toBasetype();
568 if (tab
->ty
== Ttuple
) // don't generate new scope for tuple loops
570 if (dim
< 1 || dim
> 2)
572 fs
->error("only one (value) or two (key,value) arguments for tuple foreach");
576 Type
*paramtype
= (*fs
->parameters
)[dim
-1]->type
;
579 paramtype
= paramtype
->semantic(loc
, sc
);
580 if (paramtype
->ty
== Terror
)
584 TypeTuple
*tuple
= (TypeTuple
*)tab
;
585 Statements
*statements
= new Statements();
586 //printf("aggr: op = %d, %s\n", fs->aggr->op, fs->aggr->toChars());
589 if (fs
->aggr
->op
== TOKtuple
) // expression tuple
591 te
= (TupleExp
*)fs
->aggr
;
594 else if (fs
->aggr
->op
== TOKtype
) // type tuple
596 n
= Parameter::dim(tuple
->arguments
);
600 for (size_t j
= 0; j
< n
; j
++)
602 size_t k
= (fs
->op
== TOKforeach
) ? j
: n
- 1 - j
;
603 Expression
*e
= NULL
;
608 t
= Parameter::getNth(tuple
->arguments
, k
)->type
;
609 Parameter
*p
= (*fs
->parameters
)[0];
610 Statements
*st
= new Statements();
615 if (p
->storageClass
& (STCout
| STCref
| STClazy
))
617 fs
->error("no storage class for key %s", p
->ident
->toChars());
620 p
->type
= p
->type
->semantic(loc
, sc
);
621 TY keyty
= p
->type
->ty
;
622 if (keyty
!= Tint32
&& keyty
!= Tuns32
)
624 if (global
.params
.isLP64
)
626 if (keyty
!= Tint64
&& keyty
!= Tuns64
)
628 fs
->error("foreach: key type must be int or uint, long or ulong, not %s", p
->type
->toChars());
634 fs
->error("foreach: key type must be int or uint, not %s", p
->type
->toChars());
638 Initializer
*ie
= new ExpInitializer(Loc(), new IntegerExp(k
));
639 VarDeclaration
*var
= new VarDeclaration(loc
, p
->type
, p
->ident
, ie
);
640 var
->storage_class
|= STCmanifest
;
641 st
->push(new ExpStatement(loc
, var
));
642 p
= (*fs
->parameters
)[1]; // value
645 if (p
->storageClass
& (STCout
| STClazy
) ||
646 (p
->storageClass
& STCref
&& !te
))
648 fs
->error("no storage class for value %s", p
->ident
->toChars());
654 Type
*tb
= e
->type
->toBasetype();
656 if ((tb
->ty
== Tfunction
|| tb
->ty
== Tsarray
) && e
->op
== TOKvar
)
657 ds
= ((VarExp
*)e
)->var
;
658 else if (e
->op
== TOKtemplate
)
659 ds
= ((TemplateExp
*)e
)->td
;
660 else if (e
->op
== TOKscope
)
661 ds
= ((ScopeExp
*)e
)->sds
;
662 else if (e
->op
== TOKfunction
)
664 FuncExp
*fe
= (FuncExp
*)e
;
665 ds
= fe
->td
? (Dsymbol
*)fe
->td
: fe
->fd
;
670 var
= new AliasDeclaration(loc
, p
->ident
, ds
);
671 if (p
->storageClass
& STCref
)
673 fs
->error("symbol %s cannot be ref", s
->toChars());
678 fs
->error("cannot specify element type for symbol %s", ds
->toChars());
682 else if (e
->op
== TOKtype
)
684 var
= new AliasDeclaration(loc
, p
->ident
, e
->type
);
687 fs
->error("cannot specify element type for type %s", e
->type
->toChars());
696 Initializer
*ie
= new ExpInitializer(Loc(), e
);
697 VarDeclaration
*v
= new VarDeclaration(loc
, p
->type
, p
->ident
, ie
);
698 if (p
->storageClass
& STCref
)
699 v
->storage_class
|= STCref
| STCforeach
;
700 if (e
->isConst() || e
->op
== TOKstring
||
701 e
->op
== TOKstructliteral
|| e
->op
== TOKarrayliteral
)
703 if (v
->storage_class
& STCref
)
705 fs
->error("constant value %s cannot be ref", ie
->toChars());
709 v
->storage_class
|= STCmanifest
;
716 var
= new AliasDeclaration(loc
, p
->ident
, t
);
719 fs
->error("cannot specify element type for symbol %s", s
->toChars());
723 st
->push(new ExpStatement(loc
, var
));
726 st
->push(fs
->_body
->syntaxCopy());
727 s
= new CompoundStatement(loc
, st
);
728 s
= new ScopeStatement(loc
, s
, fs
->endloc
);
732 s
= new UnrolledLoopStatement(loc
, statements
);
733 if (LabelStatement
*ls
= checkLabeledLoop(sc
, fs
))
736 s
= new CompoundStatement(loc
, new ExpStatement(te
->e0
->loc
, te
->e0
), s
);
738 s
= new CompoundStatement(loc
, new ExpStatement(loc
, vinit
), s
);
744 sym
= new ScopeDsymbol();
745 sym
->parent
= sc
->scopesym
;
746 sym
->endlinnum
= fs
->endloc
.linnum
;
747 Scope
*sc2
= sc
->push(sym
);
756 if (fs
->checkForArgTypes())
762 if (dim
< 1 || dim
> 2)
764 fs
->error("only one or two arguments for array foreach");
768 /* Look for special case of parsing char types out of char type
771 tn
= tab
->nextOf()->toBasetype();
772 if (tn
->ty
== Tchar
|| tn
->ty
== Twchar
|| tn
->ty
== Tdchar
)
774 int i
= (dim
== 1) ? 0 : 1; // index of value
775 Parameter
*p
= (*fs
->parameters
)[i
];
776 p
->type
= p
->type
->semantic(loc
, sc2
);
777 p
->type
= p
->type
->addStorageClass(p
->storageClass
);
778 tnv
= p
->type
->toBasetype();
779 if (tnv
->ty
!= tn
->ty
&&
780 (tnv
->ty
== Tchar
|| tnv
->ty
== Twchar
|| tnv
->ty
== Tdchar
))
782 if (p
->storageClass
& STCref
)
784 fs
->error("foreach: value of UTF conversion cannot be ref");
789 p
= (*fs
->parameters
)[0];
790 if (p
->storageClass
& STCref
)
792 fs
->error("foreach: key cannot be ref");
800 for (size_t i
= 0; i
< dim
; i
++)
802 // Declare parameterss
803 Parameter
*p
= (*fs
->parameters
)[i
];
804 p
->type
= p
->type
->semantic(loc
, sc2
);
805 p
->type
= p
->type
->addStorageClass(p
->storageClass
);
808 if (dim
== 2 && i
== 0)
810 var
= new VarDeclaration(loc
, p
->type
->mutableOf(), Identifier::generateId("__key"), NULL
);
811 var
->storage_class
|= STCtemp
| STCforeach
;
812 if (var
->storage_class
& (STCref
| STCout
))
813 var
->storage_class
|= STCnodtor
;
816 if (p
->storageClass
& STCref
)
818 if (var
->type
->constConv(p
->type
) <= MATCHnomatch
)
820 fs
->error("key type mismatch, %s to ref %s",
821 var
->type
->toChars(), p
->type
->toChars());
825 if (tab
->ty
== Tsarray
)
827 TypeSArray
*ta
= (TypeSArray
*)tab
;
828 IntRange dimrange
= getIntRange(ta
->dim
);
829 if (!IntRange::fromType(var
->type
).contains(dimrange
))
831 fs
->error("index type '%s' cannot cover index range 0..%llu", p
->type
->toChars(), ta
->dim
->toInteger());
834 fs
->key
->range
= new IntRange(SignExtendedNumber(0), dimrange
.imax
);
839 var
= new VarDeclaration(loc
, p
->type
, p
->ident
, NULL
);
840 var
->storage_class
|= STCforeach
;
841 var
->storage_class
|= p
->storageClass
& (STCin
| STCout
| STCref
| STC_TYPECTOR
);
842 if (var
->storage_class
& (STCref
| STCout
))
843 var
->storage_class
|= STCnodtor
;
846 if (var
->storage_class
& STCref
)
848 if (fs
->aggr
->checkModifiable(sc2
, 1) == 2)
849 var
->storage_class
|= STCctorinit
;
851 Type
*t
= tab
->nextOf();
852 if (t
->constConv(p
->type
) <= MATCHnomatch
)
854 fs
->error("argument type mismatch, %s to ref %s",
855 t
->toChars(), p
->type
->toChars());
862 /* Convert to a ForStatement
863 * foreach (key, value; a) body =>
864 * for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
865 * { T value = tmp[k]; body }
867 * foreach_reverse (key, value; a) body =>
868 * for (T[] tmp = a[], size_t key = tmp.length; key--; )
869 * { T value = tmp[k]; body }
871 Identifier
*id
= Identifier::generateId("__r");
872 ExpInitializer
*ie
= new ExpInitializer(loc
, new SliceExp(loc
, fs
->aggr
, NULL
, NULL
));
874 if (fs
->aggr
->op
== TOKarrayliteral
&&
875 !((*fs
->parameters
)[dim
- 1]->storageClass
& STCref
))
877 ArrayLiteralExp
*ale
= (ArrayLiteralExp
*)fs
->aggr
;
878 size_t edim
= ale
->elements
? ale
->elements
->dim
: 0;
879 Type
*telem
= (*fs
->parameters
)[dim
- 1]->type
;
881 // Bugzilla 12936: if telem has been specified explicitly,
882 // converting array literal elements to telem might make it @nogc.
883 fs
->aggr
= fs
->aggr
->implicitCastTo(sc
, telem
->sarrayOf(edim
));
884 if (fs
->aggr
->op
== TOKerror
)
887 // for (T[edim] tmp = a, ...)
888 tmp
= new VarDeclaration(loc
, fs
->aggr
->type
, id
, ie
);
891 tmp
= new VarDeclaration(loc
, tab
->nextOf()->arrayOf(), id
, ie
);
892 tmp
->storage_class
|= STCtemp
;
893 tmp
->endlinnum
= fs
->endloc
.linnum
;
895 Expression
*tmp_length
= new DotIdExp(loc
, new VarExp(loc
, tmp
), Id::length
);
899 Identifier
*idkey
= Identifier::generateId("__key");
900 fs
->key
= new VarDeclaration(loc
, Type::tsize_t
, idkey
, NULL
);
901 fs
->key
->storage_class
|= STCtemp
;
903 if (fs
->op
== TOKforeach_reverse
)
904 fs
->key
->_init
= new ExpInitializer(loc
, tmp_length
);
906 fs
->key
->_init
= new ExpInitializer(loc
, new IntegerExp(loc
, 0, fs
->key
->type
));
908 Statements
*cs
= new Statements();
910 cs
->push(new ExpStatement(loc
, vinit
));
911 cs
->push(new ExpStatement(loc
, tmp
));
912 cs
->push(new ExpStatement(loc
, fs
->key
));
913 Statement
*forinit
= new CompoundDeclarationStatement(loc
, cs
);
916 if (fs
->op
== TOKforeach_reverse
)
919 cond
= new PostExp(TOKminusminus
, loc
, new VarExp(loc
, fs
->key
));
924 cond
= new CmpExp(TOKlt
, loc
, new VarExp(loc
, fs
->key
), tmp_length
);
927 Expression
*increment
= NULL
;
928 if (fs
->op
== TOKforeach
)
931 increment
= new AddAssignExp(loc
, new VarExp(loc
, fs
->key
), new IntegerExp(loc
, 1, fs
->key
->type
));
934 // T value = tmp[key];
935 fs
->value
->_init
= new ExpInitializer(loc
, new IndexExp(loc
, new VarExp(loc
, tmp
), new VarExp(loc
, fs
->key
)));
936 Statement
*ds
= new ExpStatement(loc
, fs
->value
);
940 Parameter
*p
= (*fs
->parameters
)[0];
941 if ((p
->storageClass
& STCref
) && p
->type
->equals(fs
->key
->type
))
943 fs
->key
->range
= NULL
;
944 AliasDeclaration
*v
= new AliasDeclaration(loc
, p
->ident
, fs
->key
);
945 fs
->_body
= new CompoundStatement(loc
, new ExpStatement(loc
, v
), fs
->_body
);
949 ExpInitializer
*ei
= new ExpInitializer(loc
, new IdentifierExp(loc
, fs
->key
->ident
));
950 VarDeclaration
*v
= new VarDeclaration(loc
, p
->type
, p
->ident
, ei
);
951 v
->storage_class
|= STCforeach
| (p
->storageClass
& STCref
);
952 fs
->_body
= new CompoundStatement(loc
, new ExpStatement(loc
, v
), fs
->_body
);
953 if (fs
->key
->range
&& !p
->type
->isMutable())
955 /* Limit the range of the key to the specified range
957 v
->range
= new IntRange(fs
->key
->range
->imin
, fs
->key
->range
->imax
- SignExtendedNumber(1));
961 fs
->_body
= new CompoundStatement(loc
, ds
, fs
->_body
);
963 s
= new ForStatement(loc
, forinit
, cond
, increment
, fs
->_body
, fs
->endloc
);
964 if (LabelStatement
*ls
= checkLabeledLoop(sc
, fs
)) // Bugzilla 15450: don't use sc2
966 s
= semantic(s
, sc2
);
971 if (fs
->op
== TOKforeach_reverse
)
972 fs
->warning("cannot use foreach_reverse with an associative array");
973 if (fs
->checkForArgTypes())
979 taa
= (TypeAArray
*)tab
;
980 if (dim
< 1 || dim
> 2)
982 fs
->error("only one or two arguments for associative array foreach");
989 /* Prefer using opApply, if it exists
995 /* Look for range iteration, i.e. the properties
996 * .empty, .popFront, .popBack, .front and .back
997 * foreach (e; aggr) { ... }
999 * for (auto __r = aggr[]; !__r.empty; __r.popFront()) {
1000 * auto e = __r.front;
1004 AggregateDeclaration
*ad
= (tab
->ty
== Tclass
)
1005 ? (AggregateDeclaration
*)((TypeClass
*)tab
)->sym
1006 : (AggregateDeclaration
*)((TypeStruct
*)tab
)->sym
;
1007 Identifier
*idfront
;
1008 Identifier
*idpopFront
;
1009 if (fs
->op
== TOKforeach
)
1011 idfront
= Id::Ffront
;
1012 idpopFront
= Id::FpopFront
;
1016 idfront
= Id::Fback
;
1017 idpopFront
= Id::FpopBack
;
1019 Dsymbol
*sfront
= ad
->search(Loc(), idfront
);
1023 /* Generate a temporary __r and initialize it with the aggregate.
1027 if (vinit
&& fs
->aggr
->op
== TOKvar
&& ((VarExp
*)fs
->aggr
)->var
== vinit
)
1030 init
= new ExpStatement(loc
, vinit
);
1034 r
= copyToTemp(0, "__r", fs
->aggr
);
1035 init
= new ExpStatement(loc
, r
);
1037 init
= new CompoundStatement(loc
, new ExpStatement(loc
, vinit
), init
);
1041 Expression
*e
= new VarExp(loc
, r
);
1042 e
= new DotIdExp(loc
, e
, Id::Fempty
);
1043 Expression
*condition
= new NotExp(loc
, e
);
1046 e
= new VarExp(loc
, r
);
1047 Expression
*increment
= new CallExp(loc
, new DotIdExp(loc
, e
, idpopFront
));
1049 /* Declaration statement for e:
1050 * auto e = __r.idfront;
1052 e
= new VarExp(loc
, r
);
1053 Expression
*einit
= new DotIdExp(loc
, e
, idfront
);
1054 Statement
*makeargs
, *forbody
;
1057 Parameter
*p
= (*fs
->parameters
)[0];
1058 VarDeclaration
*ve
= new VarDeclaration(loc
, p
->type
, p
->ident
, new ExpInitializer(loc
, einit
));
1059 ve
->storage_class
|= STCforeach
;
1060 ve
->storage_class
|= p
->storageClass
& (STCin
| STCout
| STCref
| STC_TYPECTOR
);
1062 makeargs
= new ExpStatement(loc
, ve
);
1066 VarDeclaration
*vd
= copyToTemp(STCref
, "__front", einit
);
1067 makeargs
= new ExpStatement(loc
, vd
);
1069 Type
*tfront
= NULL
;
1070 if (FuncDeclaration
*fd
= sfront
->isFuncDeclaration())
1072 if (!fd
->functionSemantic())
1076 else if (TemplateDeclaration
*td
= sfront
->isTemplateDeclaration())
1079 if (FuncDeclaration
*f
= resolveFuncCall(loc
, sc
, td
, NULL
, tab
, &a
, 1))
1082 else if (Declaration
*d
= sfront
->isDeclaration())
1086 if (!tfront
|| tfront
->ty
== Terror
)
1089 if (tfront
->toBasetype()->ty
== Tfunction
)
1090 tfront
= tfront
->toBasetype()->nextOf();
1091 if (tfront
->ty
== Tvoid
)
1093 fs
->error("%s.front is void and has no value", oaggr
->toChars());
1097 // Resolve inout qualifier of front type
1098 tfront
= tfront
->substWildTo(tab
->mod
);
1100 Expression
*ve
= new VarExp(loc
, vd
);
1103 Expressions
*exps
= new Expressions();
1106 while (exps
->dim
< dim
)
1108 pos
= expandAliasThisTuples(exps
, pos
);
1112 if (exps
->dim
!= dim
)
1114 const char *plural
= exps
->dim
> 1 ? "s" : "";
1115 fs
->error("cannot infer argument types, expected %d argument%s, not %d",
1116 exps
->dim
, plural
, dim
);
1120 for (size_t i
= 0; i
< dim
; i
++)
1122 Parameter
*p
= (*fs
->parameters
)[i
];
1123 Expression
*exp
= (*exps
)[i
];
1125 p
->type
= exp
->type
;
1126 p
->type
= p
->type
->addStorageClass(p
->storageClass
)->semantic(loc
, sc2
);
1127 if (!exp
->implicitConvTo(p
->type
))
1130 VarDeclaration
*var
= new VarDeclaration(loc
, p
->type
, p
->ident
, new ExpInitializer(loc
, exp
));
1131 var
->storage_class
|= STCctfe
| STCref
| STCforeach
;
1132 makeargs
= new CompoundStatement(loc
, makeargs
, new ExpStatement(loc
, var
));
1137 forbody
= new CompoundStatement(loc
,
1138 makeargs
, fs
->_body
);
1140 s
= new ForStatement(loc
, init
, condition
, increment
, forbody
, fs
->endloc
);
1141 if (LabelStatement
*ls
= checkLabeledLoop(sc
, fs
))
1143 s
= semantic(s
, sc2
);
1147 fs
->error("cannot infer argument types");
1151 if (fs
->op
== TOKforeach_reverse
)
1152 fs
->deprecation("cannot use foreach_reverse with a delegate");
1155 if (fs
->checkForArgTypes())
1157 fs
->_body
= semanticNoScope(fs
->_body
, sc2
);
1162 TypeFunction
*tfld
= NULL
;
1165 FuncDeclaration
*fdapply
= sapply
->isFuncDeclaration();
1168 assert(fdapply
->type
&& fdapply
->type
->ty
== Tfunction
);
1169 tfld
= (TypeFunction
*)fdapply
->type
->semantic(loc
, sc2
);
1172 else if (tab
->ty
== Tdelegate
)
1174 tfld
= (TypeFunction
*)tab
->nextOf();
1176 //printf("tfld = %s\n", tfld->toChars());
1177 if (tfld
->parameters
->dim
== 1)
1179 Parameter
*p
= Parameter::getNth(tfld
->parameters
, 0);
1180 if (p
->type
&& p
->type
->ty
== Tdelegate
)
1182 Type
*t
= p
->type
->semantic(loc
, sc2
);
1183 assert(t
->ty
== Tdelegate
);
1184 tfld
= (TypeFunction
*)t
->nextOf();
1190 /* Turn body into the function literal:
1191 * int delegate(ref T param) { body }
1193 Parameters
*params
= new Parameters();
1194 for (size_t i
= 0; i
< dim
; i
++)
1196 Parameter
*p
= (*fs
->parameters
)[i
];
1197 StorageClass stc
= STCref
;
1200 p
->type
= p
->type
->semantic(loc
, sc2
);
1201 p
->type
= p
->type
->addStorageClass(p
->storageClass
);
1204 Parameter
*prm
= Parameter::getNth(tfld
->parameters
, i
);
1205 //printf("\tprm = %s%s\n", (prm->storageClass&STCref?"ref ":""), prm->ident->toChars());
1206 stc
= prm
->storageClass
& STCref
;
1207 id
= p
->ident
; // argument copy is not need.
1208 if ((p
->storageClass
& STCref
) != stc
)
1212 fs
->error("foreach: cannot make %s ref", p
->ident
->toChars());
1218 else if (p
->storageClass
& STCref
)
1220 // default delegate parameters are marked as ref, then
1221 // argument copy is not need.
1226 // Make a copy of the ref argument so it isn't
1229 id
= Identifier::generateId("__applyArg", (int)i
);
1231 Initializer
*ie
= new ExpInitializer(Loc(), new IdentifierExp(Loc(), id
));
1232 VarDeclaration
*v
= new VarDeclaration(Loc(), p
->type
, p
->ident
, ie
);
1233 v
->storage_class
|= STCtemp
;
1234 s
= new ExpStatement(Loc(), v
);
1235 fs
->_body
= new CompoundStatement(loc
, s
, fs
->_body
);
1237 params
->push(new Parameter(stc
, p
->type
, id
, NULL
));
1239 // Bugzilla 13840: Throwable nested function inside nothrow function is acceptable.
1240 StorageClass stc
= mergeFuncAttrs(STCsafe
| STCpure
| STCnogc
, fs
->func
);
1241 tfld
= new TypeFunction(params
, Type::tint32
, 0, LINKd
, stc
);
1242 fs
->cases
= new Statements();
1243 fs
->gotos
= new ScopeStatements();
1244 FuncLiteralDeclaration
*fld
= new FuncLiteralDeclaration(loc
, Loc(), tfld
, TOKdelegate
, fs
);
1245 fld
->fbody
= fs
->_body
;
1246 Expression
*flde
= new FuncExp(loc
, fld
);
1247 flde
= semantic(flde
, sc2
);
1248 fld
->tookAddressOf
= 0;
1250 // Resolve any forward referenced goto's
1251 for (size_t i
= 0; i
< fs
->gotos
->dim
; i
++)
1253 GotoStatement
*gs
= (GotoStatement
*)(*fs
->gotos
)[i
]->statement
;
1254 if (!gs
->label
->statement
)
1256 // 'Promote' it to this scope, and replace with a return
1257 fs
->cases
->push(gs
);
1258 s
= new ReturnStatement(Loc(), new IntegerExp(fs
->cases
->dim
+ 1));
1259 (*fs
->gotos
)[i
]->statement
= s
;
1263 Expression
*e
= NULL
;
1267 e
= new DeclarationExp(loc
, vinit
);
1268 e
= semantic(e
, sc2
);
1269 if (e
->op
== TOKerror
)
1276 Parameter
*p
= (*fs
->parameters
)[0];
1277 bool isRef
= (p
->storageClass
& STCref
) != 0;
1281 Type
*ti
= (isRef
? taa
->index
->addMod(MODconst
) : taa
->index
);
1282 if (isRef
? !ti
->constConv(ta
) : !ti
->implicitConvTo(ta
))
1284 fs
->error("foreach: index must be type %s, not %s", ti
->toChars(), ta
->toChars());
1287 p
= (*fs
->parameters
)[1];
1288 isRef
= (p
->storageClass
& STCref
) != 0;
1291 Type
*taav
= taa
->nextOf();
1292 if (isRef
? !taav
->constConv(ta
) : !taav
->implicitConvTo(ta
))
1294 fs
->error("foreach: value must be type %s, not %s", taav
->toChars(), ta
->toChars());
1299 * extern(C) int _aaApply(void*, in size_t, int delegate(void*))
1300 * _aaApply(aggr, keysize, flde)
1302 * extern(C) int _aaApply2(void*, in size_t, int delegate(void*, void*))
1303 * _aaApply2(aggr, keysize, flde)
1305 static const char *name
[2] = { "_aaApply", "_aaApply2" };
1306 static FuncDeclaration
*fdapply
[2] = { NULL
, NULL
};
1307 static TypeDelegate
*fldeTy
[2] = { NULL
, NULL
};
1309 unsigned char i
= (dim
== 2 ? 1 : 0);
1312 params
= new Parameters();
1313 params
->push(new Parameter(0, Type::tvoid
->pointerTo(), NULL
, NULL
));
1314 params
->push(new Parameter(STCin
, Type::tsize_t
, NULL
, NULL
));
1315 Parameters
* dgparams
= new Parameters
;
1316 dgparams
->push(new Parameter(0, Type::tvoidptr
, NULL
, NULL
));
1318 dgparams
->push(new Parameter(0, Type::tvoidptr
, NULL
, NULL
));
1319 fldeTy
[i
] = new TypeDelegate(new TypeFunction(dgparams
, Type::tint32
, 0, LINKd
));
1320 params
->push(new Parameter(0, fldeTy
[i
], NULL
, NULL
));
1321 fdapply
[i
] = FuncDeclaration::genCfunc(params
, Type::tint32
, name
[i
]);
1324 Expressions
*exps
= new Expressions();
1325 exps
->push(fs
->aggr
);
1326 d_uns64 keysize
= taa
->index
->size();
1327 if (keysize
== SIZE_INVALID
)
1329 assert(keysize
< UINT64_MAX
- Target::ptrsize
);
1330 keysize
= (keysize
+ (Target::ptrsize
- 1)) & ~(Target::ptrsize
- 1);
1331 // paint delegate argument to the type runtime expects
1332 if (!fldeTy
[i
]->equals(flde
->type
))
1334 flde
= new CastExp(loc
, flde
, flde
->type
);
1335 flde
->type
= fldeTy
[i
];
1337 exps
->push(new IntegerExp(Loc(), keysize
, Type::tsize_t
));
1340 ec
= new VarExp(Loc(), fdapply
[i
], false);
1341 ec
= new CallExp(loc
, ec
, exps
);
1342 ec
->type
= Type::tint32
; // don't run semantic() on ec
1344 else if (tab
->ty
== Tarray
|| tab
->ty
== Tsarray
)
1347 * _aApply(aggr, flde)
1349 static const char fntab
[9][3] =
1354 const int BUFFER_LEN
= 7+1+2+ sizeof(dim
)*3 + 1;
1355 char fdname
[BUFFER_LEN
];
1360 case Tchar
: flag
= 0; break;
1361 case Twchar
: flag
= 3; break;
1362 case Tdchar
: flag
= 6; break;
1367 case Tchar
: flag
+= 0; break;
1368 case Twchar
: flag
+= 1; break;
1369 case Tdchar
: flag
+= 2; break;
1372 const char *r
= (fs
->op
== TOKforeach_reverse
) ? "R" : "";
1373 int j
= sprintf(fdname
, "_aApply%s%.*s%llu", r
, 2, fntab
[flag
], (ulonglong
)dim
);
1374 assert(j
< BUFFER_LEN
);
1376 FuncDeclaration
*fdapply
;
1378 params
= new Parameters();
1379 params
->push(new Parameter(STCin
, tn
->arrayOf(), NULL
, NULL
));
1380 Parameters
* dgparams
= new Parameters
;
1381 dgparams
->push(new Parameter(0, Type::tvoidptr
, NULL
, NULL
));
1383 dgparams
->push(new Parameter(0, Type::tvoidptr
, NULL
, NULL
));
1384 dgty
= new TypeDelegate(new TypeFunction(dgparams
, Type::tint32
, 0, LINKd
));
1385 params
->push(new Parameter(0, dgty
, NULL
, NULL
));
1386 fdapply
= FuncDeclaration::genCfunc(params
, Type::tint32
, fdname
);
1388 if (tab
->ty
== Tsarray
)
1389 fs
->aggr
= fs
->aggr
->castTo(sc2
, tn
->arrayOf());
1391 // paint delegate argument to the type runtime expects
1392 if (!dgty
->equals(flde
->type
)) {
1393 flde
= new CastExp(loc
, flde
, flde
->type
);
1397 ec
= new VarExp(Loc(), fdapply
, false);
1398 ec
= new CallExp(loc
, ec
, fs
->aggr
, flde
);
1399 ec
->type
= Type::tint32
; // don't run semantic() on ec
1401 else if (tab
->ty
== Tdelegate
)
1406 if (fs
->aggr
->op
== TOKdelegate
&&
1407 ((DelegateExp
*)fs
->aggr
)->func
->isNested())
1409 // See Bugzilla 3560
1410 fs
->aggr
= ((DelegateExp
*)fs
->aggr
)->e1
;
1412 ec
= new CallExp(loc
, fs
->aggr
, flde
);
1413 ec
= semantic(ec
, sc2
);
1414 if (ec
->op
== TOKerror
)
1416 if (ec
->type
!= Type::tint32
)
1418 fs
->error("opApply() function for %s must return an int", tab
->toChars());
1424 if (global
.params
.vsafe
)
1425 fld
->tookAddressOf
= 1; // allocate a closure unless the opApply() uses 'scope'
1427 assert(tab
->ty
== Tstruct
|| tab
->ty
== Tclass
);
1432 ec
= new DotIdExp(loc
, fs
->aggr
, sapply
->ident
);
1433 ec
= new CallExp(loc
, ec
, flde
);
1434 ec
= semantic(ec
, sc2
);
1435 if (ec
->op
== TOKerror
)
1437 if (ec
->type
!= Type::tint32
)
1439 fs
->error("opApply() function for %s must return an int", tab
->toChars());
1443 e
= Expression::combine(e
, ec
);
1445 if (!fs
->cases
->dim
)
1447 // Easy case, a clean exit from the loop
1448 e
= new CastExp(loc
, e
, Type::tvoid
); // Bugzilla 13899
1449 s
= new ExpStatement(loc
, e
);
1453 // Construct a switch statement around the return value
1454 // of the apply function.
1455 Statements
*a
= new Statements();
1457 // default: break; takes care of cases 0 and 1
1458 s
= new BreakStatement(Loc(), NULL
);
1459 s
= new DefaultStatement(Loc(), s
);
1463 for (size_t i
= 0; i
< fs
->cases
->dim
; i
++)
1465 s
= (*fs
->cases
)[i
];
1466 s
= new CaseStatement(Loc(), new IntegerExp(i
+ 2), s
);
1470 s
= new CompoundStatement(loc
, a
);
1471 s
= new SwitchStatement(loc
, e
, s
, false);
1473 s
= semantic(s
, sc2
);
1478 s
= new ErrorStatement();
1482 fs
->error("foreach: %s is not an aggregate type", fs
->aggr
->type
->toChars());
1490 void visit(ForeachRangeStatement
*fs
)
1492 //printf("ForeachRangeStatement::semantic() %p\n", fs);
1494 fs
->lwr
= semantic(fs
->lwr
, sc
);
1495 fs
->lwr
= resolveProperties(sc
, fs
->lwr
);
1496 fs
->lwr
= fs
->lwr
->optimize(WANTvalue
);
1499 fs
->error("invalid range lower bound %s", fs
->lwr
->toChars());
1504 fs
->upr
= semantic(fs
->upr
, sc
);
1505 fs
->upr
= resolveProperties(sc
, fs
->upr
);
1506 fs
->upr
= fs
->upr
->optimize(WANTvalue
);
1509 fs
->error("invalid range upper bound %s", fs
->upr
->toChars());
1515 fs
->prm
->type
= fs
->prm
->type
->semantic(loc
, sc
);
1516 fs
->prm
->type
= fs
->prm
->type
->addStorageClass(fs
->prm
->storageClass
);
1517 fs
->lwr
= fs
->lwr
->implicitCastTo(sc
, fs
->prm
->type
);
1519 if (fs
->upr
->implicitConvTo(fs
->prm
->type
) || (fs
->prm
->storageClass
& STCref
))
1521 fs
->upr
= fs
->upr
->implicitCastTo(sc
, fs
->prm
->type
);
1525 // See if upr-1 fits in prm->type
1526 Expression
*limit
= new MinExp(loc
, fs
->upr
, new IntegerExp(1));
1527 limit
= semantic(limit
, sc
);
1528 limit
= limit
->optimize(WANTvalue
);
1529 if (!limit
->implicitConvTo(fs
->prm
->type
))
1531 fs
->upr
= fs
->upr
->implicitCastTo(sc
, fs
->prm
->type
);
1537 /* Must infer types from lwr and upr
1539 Type
*tlwr
= fs
->lwr
->type
->toBasetype();
1540 if (tlwr
->ty
== Tstruct
|| tlwr
->ty
== Tclass
)
1542 /* Just picking the first really isn't good enough.
1544 fs
->prm
->type
= fs
->lwr
->type
;
1546 else if (fs
->lwr
->type
== fs
->upr
->type
)
1548 /* Same logic as CondExp ?lwr:upr
1550 fs
->prm
->type
= fs
->lwr
->type
;
1554 AddExp
ea(loc
, fs
->lwr
, fs
->upr
);
1555 if (typeCombine(&ea
, sc
))
1557 fs
->prm
->type
= ea
.type
;
1561 fs
->prm
->type
= fs
->prm
->type
->addStorageClass(fs
->prm
->storageClass
);
1563 if (fs
->prm
->type
->ty
== Terror
||
1564 fs
->lwr
->op
== TOKerror
||
1565 fs
->upr
->op
== TOKerror
)
1570 /* Convert to a for loop:
1571 * foreach (key; lwr .. upr) =>
1572 * for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
1574 * foreach_reverse (key; lwr .. upr) =>
1575 * for (auto tmp = lwr, auto key = upr; key-- > tmp;)
1577 ExpInitializer
*ie
= new ExpInitializer(loc
, (fs
->op
== TOKforeach
) ? fs
->lwr
: fs
->upr
);
1578 fs
->key
= new VarDeclaration(loc
, fs
->upr
->type
->mutableOf(), Identifier::generateId("__key"), ie
);
1579 fs
->key
->storage_class
|= STCtemp
;
1580 SignExtendedNumber lower
= getIntRange(fs
->lwr
).imin
;
1581 SignExtendedNumber upper
= getIntRange(fs
->upr
).imax
;
1584 fs
->key
->range
= new IntRange(lower
, upper
);
1587 Identifier
*id
= Identifier::generateId("__limit");
1588 ie
= new ExpInitializer(loc
, (fs
->op
== TOKforeach
) ? fs
->upr
: fs
->lwr
);
1589 VarDeclaration
*tmp
= new VarDeclaration(loc
, fs
->upr
->type
, id
, ie
);
1590 tmp
->storage_class
|= STCtemp
;
1592 Statements
*cs
= new Statements();
1593 // Keep order of evaluation as lwr, then upr
1594 if (fs
->op
== TOKforeach
)
1596 cs
->push(new ExpStatement(loc
, fs
->key
));
1597 cs
->push(new ExpStatement(loc
, tmp
));
1601 cs
->push(new ExpStatement(loc
, tmp
));
1602 cs
->push(new ExpStatement(loc
, fs
->key
));
1604 Statement
*forinit
= new CompoundDeclarationStatement(loc
, cs
);
1607 if (fs
->op
== TOKforeach_reverse
)
1609 cond
= new PostExp(TOKminusminus
, loc
, new VarExp(loc
, fs
->key
));
1610 if (fs
->prm
->type
->isscalar())
1613 cond
= new CmpExp(TOKgt
, loc
, cond
, new VarExp(loc
, tmp
));
1618 cond
= new EqualExp(TOKnotequal
, loc
, cond
, new VarExp(loc
, tmp
));
1623 if (fs
->prm
->type
->isscalar())
1626 cond
= new CmpExp(TOKlt
, loc
, new VarExp(loc
, fs
->key
), new VarExp(loc
, tmp
));
1631 cond
= new EqualExp(TOKnotequal
, loc
, new VarExp(loc
, fs
->key
), new VarExp(loc
, tmp
));
1635 Expression
*increment
= NULL
;
1636 if (fs
->op
== TOKforeach
)
1639 //increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
1640 increment
= new PreExp(TOKpreplusplus
, loc
, new VarExp(loc
, fs
->key
));
1643 if ((fs
->prm
->storageClass
& STCref
) && fs
->prm
->type
->equals(fs
->key
->type
))
1645 fs
->key
->range
= NULL
;
1646 AliasDeclaration
*v
= new AliasDeclaration(loc
, fs
->prm
->ident
, fs
->key
);
1647 fs
->_body
= new CompoundStatement(loc
, new ExpStatement(loc
, v
), fs
->_body
);
1651 ie
= new ExpInitializer(loc
, new CastExp(loc
, new VarExp(loc
, fs
->key
), fs
->prm
->type
));
1652 VarDeclaration
*v
= new VarDeclaration(loc
, fs
->prm
->type
, fs
->prm
->ident
, ie
);
1653 v
->storage_class
|= STCtemp
| STCforeach
| (fs
->prm
->storageClass
& STCref
);
1654 fs
->_body
= new CompoundStatement(loc
, new ExpStatement(loc
, v
), fs
->_body
);
1655 if (fs
->key
->range
&& !fs
->prm
->type
->isMutable())
1657 /* Limit the range of the key to the specified range
1659 v
->range
= new IntRange(fs
->key
->range
->imin
, fs
->key
->range
->imax
- SignExtendedNumber(1));
1662 if (fs
->prm
->storageClass
& STCref
)
1664 if (fs
->key
->type
->constConv(fs
->prm
->type
) <= MATCHnomatch
)
1666 fs
->error("prmument type mismatch, %s to ref %s",
1667 fs
->key
->type
->toChars(), fs
->prm
->type
->toChars());
1672 ForStatement
*s
= new ForStatement(loc
, forinit
, cond
, increment
, fs
->_body
, fs
->endloc
);
1673 if (LabelStatement
*ls
= checkLabeledLoop(sc
, fs
))
1675 result
= semantic(s
, sc
);
1678 void visit(IfStatement
*ifs
)
1680 // Evaluate at runtime
1681 unsigned cs0
= sc
->callSuper
;
1683 unsigned *fi0
= sc
->saveFieldInit();
1684 unsigned *fi1
= NULL
;
1686 // check in syntax level
1687 ifs
->condition
= checkAssignmentAsCondition(ifs
->condition
);
1689 ScopeDsymbol
*sym
= new ScopeDsymbol();
1690 sym
->parent
= sc
->scopesym
;
1691 sym
->endlinnum
= ifs
->endloc
.linnum
;
1692 Scope
*scd
= sc
->push(sym
);
1695 /* Declare prm, which we will set to be the
1696 * result of condition.
1698 ExpInitializer
*ei
= new ExpInitializer(ifs
->loc
, ifs
->condition
);
1699 ifs
->match
= new VarDeclaration(ifs
->loc
, ifs
->prm
->type
, ifs
->prm
->ident
, ei
);
1700 ifs
->match
->parent
= sc
->func
;
1701 ifs
->match
->storage_class
|= ifs
->prm
->storageClass
;
1702 ifs
->match
->semantic(scd
);
1704 DeclarationExp
*de
= new DeclarationExp(ifs
->loc
, ifs
->match
);
1705 VarExp
*ve
= new VarExp(ifs
->loc
, ifs
->match
);
1706 ifs
->condition
= new CommaExp(ifs
->loc
, de
, ve
);
1707 ifs
->condition
= semantic(ifs
->condition
, scd
);
1709 if (ifs
->match
->edtor
)
1711 Statement
*sdtor
= new DtorExpStatement(ifs
->loc
, ifs
->match
->edtor
, ifs
->match
);
1712 sdtor
= new OnScopeStatement(ifs
->loc
, TOKon_scope_exit
, sdtor
);
1713 ifs
->ifbody
= new CompoundStatement(ifs
->loc
, sdtor
, ifs
->ifbody
);
1714 ifs
->match
->storage_class
|= STCnodtor
;
1719 if (ifs
->condition
->op
== TOKdotid
)
1720 ((DotIdExp
*)ifs
->condition
)->noderef
= true;
1722 ifs
->condition
= semantic(ifs
->condition
, sc
);
1723 ifs
->condition
= resolveProperties(sc
, ifs
->condition
);
1724 ifs
->condition
= ifs
->condition
->addDtorHook(sc
);
1726 ifs
->condition
= checkGC(sc
, ifs
->condition
);
1728 // Convert to boolean after declaring prm so this works:
1729 // if (S prm = S()) {}
1730 // where S is a struct that defines opCast!bool.
1731 ifs
->condition
= ifs
->condition
->toBoolean(sc
);
1733 // If we can short-circuit evaluate the if statement, don't do the
1734 // semantic analysis of the skipped code.
1735 // This feature allows a limited form of conditional compilation.
1736 ifs
->condition
= ifs
->condition
->optimize(WANTvalue
);
1737 ifs
->ifbody
= semanticNoScope(ifs
->ifbody
, scd
);
1740 cs1
= sc
->callSuper
;
1741 fi1
= sc
->fieldinit
;
1742 sc
->callSuper
= cs0
;
1743 sc
->fieldinit
= fi0
;
1745 ifs
->elsebody
= semanticScope(ifs
->elsebody
, sc
, NULL
, NULL
);
1746 sc
->mergeCallSuper(ifs
->loc
, cs1
);
1747 sc
->mergeFieldInit(ifs
->loc
, fi1
);
1749 if (ifs
->condition
->op
== TOKerror
||
1750 (ifs
->ifbody
&& ifs
->ifbody
->isErrorStatement()) ||
1751 (ifs
->elsebody
&& ifs
->elsebody
->isErrorStatement()))
1758 void visit(ConditionalStatement
*cs
)
1760 //printf("ConditionalStatement::semantic()\n");
1762 // If we can short-circuit evaluate the if statement, don't do the
1763 // semantic analysis of the skipped code.
1764 // This feature allows a limited form of conditional compilation.
1765 if (cs
->condition
->include(sc
, NULL
))
1767 DebugCondition
*dc
= cs
->condition
->isDebugCondition();
1771 sc
->flags
|= SCOPEdebug
;
1772 cs
->ifbody
= semantic(cs
->ifbody
, sc
);
1776 cs
->ifbody
= semantic(cs
->ifbody
, sc
);
1777 result
= cs
->ifbody
;
1782 cs
->elsebody
= semantic(cs
->elsebody
, sc
);
1783 result
= cs
->elsebody
;
1787 void visit(PragmaStatement
*ps
)
1789 // Should be merged with PragmaDeclaration
1790 //printf("PragmaStatement::semantic() %s\n", ps->toChars());
1791 //printf("body = %p\n", ps->_body);
1792 if (ps
->ident
== Id::msg
)
1796 for (size_t i
= 0; i
< ps
->args
->dim
; i
++)
1798 Expression
*e
= (*ps
->args
)[i
];
1800 sc
= sc
->startCTFE();
1801 e
= semantic(e
, sc
);
1802 e
= resolveProperties(sc
, e
);
1804 // pragma(msg) is allowed to contain types as well as expressions
1805 e
= ctfeInterpretForPragmaMsg(e
);
1806 if (e
->op
== TOKerror
)
1808 errorSupplemental(ps
->loc
, "while evaluating pragma(msg, %s)", (*ps
->args
)[i
]->toChars());
1811 StringExp
*se
= e
->toStringExp();
1814 se
= se
->toUTF8(sc
);
1815 fprintf(stderr
, "%.*s", (int)se
->len
, (char *)se
->string
);
1818 fprintf(stderr
, "%s", e
->toChars());
1820 fprintf(stderr
, "\n");
1823 else if (ps
->ident
== Id::lib
)
1825 /* Should this be allowed?
1827 ps
->error("pragma(lib) not allowed as statement");
1830 else if (ps
->ident
== Id::startaddress
)
1832 if (!ps
->args
|| ps
->args
->dim
!= 1)
1833 ps
->error("function name expected for start address");
1836 Expression
*e
= (*ps
->args
)[0];
1838 sc
= sc
->startCTFE();
1839 e
= semantic(e
, sc
);
1840 e
= resolveProperties(sc
, e
);
1843 e
= e
->ctfeInterpret();
1845 Dsymbol
*sa
= getDsymbol(e
);
1846 if (!sa
|| !sa
->isFuncDeclaration())
1848 ps
->error("function name expected for start address, not '%s'", e
->toChars());
1853 ps
->_body
= semantic(ps
->_body
, sc
);
1854 if (ps
->_body
->isErrorStatement())
1864 else if (ps
->ident
== Id::Pinline
)
1866 PINLINE inlining
= PINLINEdefault
;
1867 if (!ps
->args
|| ps
->args
->dim
== 0)
1868 inlining
= PINLINEdefault
;
1869 else if (!ps
->args
|| ps
->args
->dim
!= 1)
1871 ps
->error("boolean expression expected for pragma(inline)");
1876 Expression
*e
= (*ps
->args
)[0];
1878 if (e
->op
!= TOKint64
|| !e
->type
->equals(Type::tbool
))
1880 ps
->error("pragma(inline, true or false) expected, not %s", e
->toChars());
1884 if (e
->isBool(true))
1885 inlining
= PINLINEalways
;
1886 else if (e
->isBool(false))
1887 inlining
= PINLINEnever
;
1889 FuncDeclaration
*fd
= sc
->func
;
1892 ps
->error("pragma(inline) is not inside a function");
1895 fd
->inlining
= inlining
;
1900 ps
->error("unrecognized pragma(%s)", ps
->ident
->toChars());
1906 ps
->_body
= semantic(ps
->_body
, sc
);
1915 void visit(StaticAssertStatement
*s
)
1917 s
->sa
->semantic2(sc
);
1920 void visit(SwitchStatement
*ss
)
1922 //printf("SwitchStatement::semantic(%p)\n", ss);
1926 result
= ss
; // already run
1929 bool conditionError
= false;
1930 ss
->condition
= semantic(ss
->condition
, sc
);
1931 ss
->condition
= resolveProperties(sc
, ss
->condition
);
1934 TypeEnum
*te
= NULL
;
1935 while (ss
->condition
->op
!= TOKerror
)
1937 // preserve enum type for final switches
1938 if (ss
->condition
->type
->ty
== Tenum
)
1939 te
= (TypeEnum
*)ss
->condition
->type
;
1940 if (ss
->condition
->type
->isString())
1942 // If it's not an array, cast it to one
1943 if (ss
->condition
->type
->ty
!= Tarray
)
1945 ss
->condition
= ss
->condition
->implicitCastTo(sc
, ss
->condition
->type
->nextOf()->arrayOf());
1947 ss
->condition
->type
= ss
->condition
->type
->constOf();
1950 ss
->condition
= integralPromotions(ss
->condition
, sc
);
1951 if (ss
->condition
->op
!= TOKerror
&& ss
->condition
->type
->isintegral())
1954 AggregateDeclaration
*ad
= isAggregate(ss
->condition
->type
);
1955 if (ad
&& ad
->aliasthis
&& ss
->condition
->type
!= att
)
1957 if (!att
&& ss
->condition
->type
->checkAliasThisRec())
1958 att
= ss
->condition
->type
;
1959 if (Expression
*e
= resolveAliasThis(sc
, ss
->condition
, true))
1966 if (ss
->condition
->op
!= TOKerror
)
1968 ss
->error("'%s' must be of integral or string type, it is a %s",
1969 ss
->condition
->toChars(), ss
->condition
->type
->toChars());
1970 conditionError
= true;
1974 ss
->condition
= ss
->condition
->optimize(WANTvalue
);
1975 ss
->condition
= checkGC(sc
, ss
->condition
);
1976 if (ss
->condition
->op
== TOKerror
)
1977 conditionError
= true;
1979 bool needswitcherror
= false;
1981 ss
->lastVar
= sc
->lastVar
;
1987 ss
->cases
= new CaseStatements();
1988 sc
->noctor
++; // BUG: should use Scope::mergeCallSuper() for each case instead
1989 ss
->_body
= semantic(ss
->_body
, sc
);
1992 if (conditionError
|| ss
->_body
->isErrorStatement())
1995 // Resolve any goto case's with exp
1996 for (size_t i
= 0; i
< ss
->gotoCases
.dim
; i
++)
1998 GotoCaseStatement
*gcs
= ss
->gotoCases
[i
];
2002 gcs
->error("no case statement following goto case;");
2006 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2010 for (size_t j
= 0; j
< scx
->sw
->cases
->dim
; j
++)
2012 CaseStatement
*cs
= (*scx
->sw
->cases
)[j
];
2014 if (cs
->exp
->equals(gcs
->exp
))
2021 gcs
->error("case %s not found", gcs
->exp
->toChars());
2030 Type
*t
= ss
->condition
->type
;
2032 EnumDeclaration
*ed
= NULL
;
2033 if (t
&& ((ds
= t
->toDsymbol(sc
)) != NULL
))
2034 ed
= ds
->isEnumDeclaration(); // typedef'ed enum
2035 if (!ed
&& te
&& ((ds
= te
->toDsymbol(sc
)) != NULL
))
2036 ed
= ds
->isEnumDeclaration();
2039 size_t dim
= ed
->members
->dim
;
2040 for (size_t i
= 0; i
< dim
; i
++)
2042 EnumMember
*em
= (*ed
->members
)[i
]->isEnumMember();
2045 for (size_t j
= 0; j
< ss
->cases
->dim
; j
++)
2047 CaseStatement
*cs
= (*ss
->cases
)[j
];
2048 if (cs
->exp
->equals(em
->value()) ||
2049 (!cs
->exp
->type
->isString() && !em
->value()->type
->isString() &&
2050 cs
->exp
->toInteger() == em
->value()->toInteger()))
2053 ss
->error("enum member %s not represented in final switch", em
->toChars());
2061 needswitcherror
= true;
2064 if (!sc
->sw
->sdefault
&& (!ss
->isFinal
|| needswitcherror
|| global
.params
.useAssert
))
2066 ss
->hasNoDefault
= 1;
2068 if (!ss
->isFinal
&& !ss
->_body
->isErrorStatement())
2069 ss
->error("switch statement without a default; use 'final switch' or add 'default: assert(0);' or add 'default: break;'");
2071 // Generate runtime error if the default is hit
2072 Statements
*a
= new Statements();
2073 CompoundStatement
*cs
;
2076 if (global
.params
.useSwitchError
)
2077 s
= new SwitchErrorStatement(ss
->loc
);
2079 s
= new ExpStatement(ss
->loc
, new HaltExp(ss
->loc
));
2082 sc
->sw
->sdefault
= new DefaultStatement(ss
->loc
, s
);
2084 if (blockExit(ss
->_body
, sc
->func
, false) & BEfallthru
)
2085 a
->push(new BreakStatement(Loc(), NULL
));
2086 a
->push(sc
->sw
->sdefault
);
2087 cs
= new CompoundStatement(ss
->loc
, a
);
2091 if (ss
->checkLabel())
2100 result
= new ErrorStatement();
2103 void visit(CaseStatement
*cs
)
2105 SwitchStatement
*sw
= sc
->sw
;
2106 bool errors
= false;
2108 //printf("CaseStatement::semantic() %s\n", cs->toChars());
2109 sc
= sc
->startCTFE();
2110 cs
->exp
= semantic(cs
->exp
, sc
);
2111 cs
->exp
= resolveProperties(sc
, cs
->exp
);
2115 cs
->exp
= cs
->exp
->implicitCastTo(sc
, sw
->condition
->type
);
2116 cs
->exp
= cs
->exp
->optimize(WANTvalue
| WANTexpand
);
2118 Expression
*e
= cs
->exp
;
2119 // Remove all the casts the user and/or implicitCastTo may introduce
2120 // otherwise we'd sometimes fail the check below.
2121 while (e
->op
== TOKcast
)
2122 e
= ((CastExp
*)e
)->e1
;
2124 /* This is where variables are allowed as case expressions.
2126 if (e
->op
== TOKvar
)
2128 VarExp
*ve
= (VarExp
*)e
;
2129 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
2130 Type
*t
= cs
->exp
->type
->toBasetype();
2131 if (v
&& (t
->isintegral() || t
->ty
== Tclass
))
2133 /* Flag that we need to do special code generation
2134 * for this, i.e. generate a sequence of if-then-else
2138 /* TODO check if v can be uninitialized at that point.
2140 if (!v
->isConst() && !v
->isImmutable())
2142 cs
->deprecation("case variables have to be const or immutable");
2147 cs
->error("case variables not allowed in final switch statements");
2151 /* Also check if the VarExp is declared in a scope outside of this one.
2152 * 'scx' is set to the scope of the switch statement.
2154 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2156 if (scx
->enclosing
&& scx
->enclosing
->sw
== sw
)
2158 assert(scx
->sw
== sw
);
2160 if (!scx
->search(cs
->exp
->loc
, v
->ident
, NULL
))
2162 cs
->error("case variable `%s` declared at %s cannot be declared in switch body",
2163 v
->toChars(), v
->loc
.toChars());
2172 cs
->exp
= cs
->exp
->ctfeInterpret();
2174 if (StringExp
*se
= cs
->exp
->toStringExp())
2176 else if (cs
->exp
->op
!= TOKint64
&& cs
->exp
->op
!= TOKerror
)
2178 cs
->error("case must be a string or an integral constant, not %s", cs
->exp
->toChars());
2183 for (size_t i
= 0; i
< sw
->cases
->dim
; i
++)
2185 CaseStatement
*cs2
= (*sw
->cases
)[i
];
2187 //printf("comparing '%s' with '%s'\n", cs->exp->toChars(), cs2->exp->toChars());
2188 if (cs2
->exp
->equals(cs
->exp
))
2190 cs
->error("duplicate case %s in switch statement", cs
->exp
->toChars());
2196 sw
->cases
->push(cs
);
2198 // Resolve any goto case's with no exp to this case statement
2199 for (size_t i
= 0; i
< sw
->gotoCases
.dim
; )
2201 GotoCaseStatement
*gcs
= sw
->gotoCases
[i
];
2206 sw
->gotoCases
.remove(i
); // remove from array
2212 if (sc
->sw
->tf
!= sc
->tf
)
2214 cs
->error("switch and case are in different finally blocks");
2220 cs
->error("case not in switch statement");
2223 cs
->statement
= semantic(cs
->statement
, sc
);
2224 if (cs
->statement
->isErrorStatement())
2226 result
= cs
->statement
;
2229 if (errors
|| cs
->exp
->op
== TOKerror
)
2232 cs
->lastVar
= sc
->lastVar
;
2236 void visit(CaseRangeStatement
*crs
)
2238 SwitchStatement
*sw
= sc
->sw
;
2241 crs
->error("case range not in switch statement");
2245 //printf("CaseRangeStatement::semantic() %s\n", toChars());
2246 bool errors
= false;
2249 crs
->error("case ranges not allowed in final switch");
2253 sc
= sc
->startCTFE();
2254 crs
->first
= semantic(crs
->first
, sc
);
2255 crs
->first
= resolveProperties(sc
, crs
->first
);
2257 crs
->first
= crs
->first
->implicitCastTo(sc
, sw
->condition
->type
);
2258 crs
->first
= crs
->first
->ctfeInterpret();
2260 sc
= sc
->startCTFE();
2261 crs
->last
= semantic(crs
->last
, sc
);
2262 crs
->last
= resolveProperties(sc
, crs
->last
);
2264 crs
->last
= crs
->last
->implicitCastTo(sc
, sw
->condition
->type
);
2265 crs
->last
= crs
->last
->ctfeInterpret();
2267 if (crs
->first
->op
== TOKerror
|| crs
->last
->op
== TOKerror
|| errors
)
2270 semantic(crs
->statement
, sc
);
2274 uinteger_t fval
= crs
->first
->toInteger();
2275 uinteger_t lval
= crs
->last
->toInteger();
2278 if ( (crs
->first
->type
->isunsigned() && fval
> lval
) ||
2279 (!crs
->first
->type
->isunsigned() && (sinteger_t
)fval
> (sinteger_t
)lval
))
2281 crs
->error("first case %s is greater than last case %s",
2282 crs
->first
->toChars(), crs
->last
->toChars());
2287 if (lval
- fval
> 256)
2289 crs
->error("had %llu cases which is more than 256 cases in case range", lval
- fval
);
2297 /* This works by replacing the CaseRange with an array of Case's.
2299 * case a: .. case b: s;
2307 Statements
*statements
= new Statements();
2308 for (uinteger_t i
= fval
; i
!= lval
+ 1; i
++)
2310 Statement
*s
= crs
->statement
;
2311 if (i
!= lval
) // if not last case
2312 s
= new ExpStatement(crs
->loc
, (Expression
*)NULL
);
2313 Expression
*e
= new IntegerExp(crs
->loc
, i
, crs
->first
->type
);
2314 Statement
*cs
= new CaseStatement(crs
->loc
, e
, s
);
2315 statements
->push(cs
);
2317 Statement
*s
= new CompoundStatement(crs
->loc
, statements
);
2318 s
= semantic(s
, sc
);
2322 void visit(DefaultStatement
*ds
)
2324 //printf("DefaultStatement::semantic()\n");
2325 bool errors
= false;
2328 if (sc
->sw
->sdefault
)
2330 ds
->error("switch statement already has a default");
2333 sc
->sw
->sdefault
= ds
;
2335 if (sc
->sw
->tf
!= sc
->tf
)
2337 ds
->error("switch and default are in different finally blocks");
2340 if (sc
->sw
->isFinal
)
2342 ds
->error("default statement not allowed in final switch statement");
2348 ds
->error("default not in switch statement");
2351 ds
->statement
= semantic(ds
->statement
, sc
);
2352 if (errors
|| ds
->statement
->isErrorStatement())
2355 ds
->lastVar
= sc
->lastVar
;
2359 void visit(GotoDefaultStatement
*gds
)
2364 gds
->error("goto default not in switch statement");
2367 if (gds
->sw
->isFinal
)
2369 gds
->error("goto default not allowed in final switch statement");
2375 void visit(GotoCaseStatement
*gcs
)
2379 gcs
->error("goto case not in switch statement");
2385 gcs
->exp
= semantic(gcs
->exp
, sc
);
2386 gcs
->exp
= gcs
->exp
->implicitCastTo(sc
, sc
->sw
->condition
->type
);
2387 gcs
->exp
= gcs
->exp
->optimize(WANTvalue
);
2388 if (gcs
->exp
->op
== TOKerror
)
2392 sc
->sw
->gotoCases
.push(gcs
);
2396 void visit(ReturnStatement
*rs
)
2398 //printf("ReturnStatement::semantic() %s\n", toChars());
2400 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
2403 fd
= fd
->fes
->func
; // fd is now function enclosing foreach
2405 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
2406 assert(tf
->ty
== Tfunction
);
2408 if (rs
->exp
&& rs
->exp
->op
== TOKvar
&& ((VarExp
*)rs
->exp
)->var
== fd
->vresult
)
2413 assert(rs
->caseDim
== 0);
2414 sc
->fes
->cases
->push(rs
);
2415 result
= new ReturnStatement(Loc(), new IntegerExp(sc
->fes
->cases
->dim
+ 1));
2418 if (fd
->returnLabel
)
2420 GotoStatement
*gs
= new GotoStatement(rs
->loc
, Id::returnLabel
);
2421 gs
->label
= fd
->returnLabel
;
2427 fd
->returns
= new ReturnStatements();
2428 fd
->returns
->push(rs
);
2433 Type
*tret
= tf
->next
;
2434 Type
*tbret
= tret
? tret
->toBasetype() : NULL
;
2436 bool inferRef
= (tf
->isref
&& (fd
->storage_class
& STCauto
));
2437 Expression
*e0
= NULL
;
2439 bool errors
= false;
2440 if (sc
->flags
& SCOPEcontract
)
2442 rs
->error("return statements cannot be in contracts");
2445 if (sc
->os
&& sc
->os
->tok
!= TOKon_scope_failure
)
2447 rs
->error("return statements cannot be in %s bodies", Token::toChars(sc
->os
->tok
));
2452 rs
->error("return statements cannot be in finally bodies");
2456 if (fd
->isCtorDeclaration())
2460 rs
->error("cannot return expression from constructor");
2464 // Constructors implicitly do:
2466 rs
->exp
= new ThisExp(Loc());
2467 rs
->exp
->type
= tret
;
2471 fd
->hasReturnExp
|= (fd
->hasReturnExp
& 1 ? 16 : 1);
2473 FuncLiteralDeclaration
*fld
= fd
->isFuncLiteralDeclaration();
2475 rs
->exp
= inferType(rs
->exp
, tret
);
2476 else if (fld
&& fld
->treq
)
2477 rs
->exp
= inferType(rs
->exp
, fld
->treq
->nextOf()->nextOf());
2478 rs
->exp
= semantic(rs
->exp
, sc
);
2480 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
2481 if (rs
->exp
->op
== TOKtype
)
2482 rs
->exp
= resolveAliasThis(sc
, rs
->exp
);
2484 rs
->exp
= resolveProperties(sc
, rs
->exp
);
2485 if (rs
->exp
->checkType())
2486 rs
->exp
= new ErrorExp();
2487 if (FuncDeclaration
*f
= isFuncAddress(rs
->exp
))
2489 if (fd
->inferRetType
&& f
->checkForwardRef(rs
->exp
->loc
))
2490 rs
->exp
= new ErrorExp();
2492 if (checkNonAssignmentArrayOp(rs
->exp
))
2493 rs
->exp
= new ErrorExp();
2495 // Extract side-effect part
2496 rs
->exp
= Expression::extractLast(rs
->exp
, &e0
);
2497 if (rs
->exp
->op
== TOKcall
)
2498 rs
->exp
= valueNoDtor(rs
->exp
);
2501 e0
= e0
->optimize(WANTvalue
);
2503 /* Void-return function can have void typed expression
2504 * on return statement.
2506 if ((tbret
&& tbret
->ty
== Tvoid
) || rs
->exp
->type
->ty
== Tvoid
)
2508 if (rs
->exp
->type
->ty
!= Tvoid
)
2510 rs
->error("cannot return non-void from void function");
2513 rs
->exp
= new CastExp(rs
->loc
, rs
->exp
, Type::tvoid
);
2514 rs
->exp
= semantic(rs
->exp
, sc
);
2522 e0
= Expression::combine(e0
, rs
->exp
);
2526 e0
= checkGC(sc
, e0
);
2531 if (fd
->inferRetType
) // infer return type
2535 tf
->next
= rs
->exp
->type
;
2537 else if (tret
->ty
!= Terror
&& !rs
->exp
->type
->equals(tret
))
2539 int m1
= rs
->exp
->type
->implicitConvTo(tret
);
2540 int m2
= tret
->implicitConvTo(rs
->exp
->type
);
2541 //printf("exp->type = %s m2<-->m1 tret %s\n", rs->exp->type->toChars(), tret->toChars());
2542 //printf("m1 = %d, m2 = %d\n", m1, m2);
2547 tf
->next
= rs
->exp
->type
;
2550 else if (rs
->exp
->op
!= TOKerror
)
2552 rs
->error("mismatched function return type inference of %s and %s",
2553 rs
->exp
->type
->toChars(), tret
->toChars());
2555 tf
->next
= Type::terror
;
2560 tbret
= tret
->toBasetype();
2563 if (inferRef
) // deduce 'auto ref'
2565 /* Determine "refness" of function return:
2566 * if it's an lvalue, return by ref, else return by value
2568 if (rs
->exp
->isLvalue())
2570 /* May return by ref
2572 if (checkReturnEscapeRef(sc
, rs
->exp
, true))
2573 tf
->isref
= false; // return by value
2576 tf
->isref
= false; // return by value
2578 /* The "refness" is determined by all of return statements.
2580 * return 3; return x; // ok, x can be a value
2581 * return x; return 3; // ok, x can be a value
2586 if (fd
->nrvo_can
&& rs
->exp
->op
== TOKvar
)
2588 VarExp
*ve
= (VarExp
*)rs
->exp
;
2589 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
2593 // Function returns a reference
2597 else if (!v
|| v
->isOut() || v
->isRef())
2599 else if (fd
->nrvo_var
== NULL
)
2601 if (!v
->isDataseg() && !v
->isParameter() && v
->toParent2() == fd
)
2603 //printf("Setting nrvo to %s\n", v->toChars());
2609 else if (fd
->nrvo_var
!= v
)
2612 else //if (!exp->isLvalue()) // keep NRVO-ability
2620 // infer return type
2621 if (fd
->inferRetType
)
2623 if (tf
->next
&& tf
->next
->ty
!= Tvoid
)
2625 if (tf
->next
->ty
!= Terror
)
2627 rs
->error("mismatched function return type inference of void and %s",
2628 tf
->next
->toChars());
2631 tf
->next
= Type::terror
;
2634 tf
->next
= Type::tvoid
;
2637 tbret
= tret
->toBasetype();
2640 if (inferRef
) // deduce 'auto ref'
2643 if (tbret
->ty
!= Tvoid
) // if non-void return
2645 if (tbret
->ty
!= Terror
)
2646 rs
->error("return expression expected");
2649 else if (fd
->isMain())
2651 // main() returns 0, even if it returns void
2652 rs
->exp
= new IntegerExp(0);
2656 // If any branches have called a ctor, but this branch hasn't, it's an error
2657 if (sc
->callSuper
& CSXany_ctor
&&
2658 !(sc
->callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)))
2660 rs
->error("return without calling constructor");
2663 sc
->callSuper
|= CSXreturn
;
2666 AggregateDeclaration
*ad
= fd
->isMember2();
2668 size_t dim
= sc
->fieldinit_dim
;
2669 for (size_t i
= 0; i
< dim
; i
++)
2671 VarDeclaration
*v
= ad
->fields
[i
];
2672 bool mustInit
= (v
->storage_class
& STCnodefaultctor
||
2673 v
->type
->needsNested());
2674 if (mustInit
&& !(sc
->fieldinit
[i
] & CSXthis_ctor
))
2676 rs
->error("an earlier return statement skips field %s initialization", v
->toChars());
2679 sc
->fieldinit
[i
] |= CSXreturn
;
2690 // Send out "case receiver" statement to the foreach.
2692 Statement
*s
= new ReturnStatement(Loc(), rs
->exp
);
2693 sc
->fes
->cases
->push(s
);
2695 // Immediately rewrite "this" return statement as:
2696 // return cases->dim+1;
2697 rs
->exp
= new IntegerExp(sc
->fes
->cases
->dim
+ 1);
2700 result
= new CompoundStatement(rs
->loc
, new ExpStatement(rs
->loc
, e0
), rs
);
2708 fd
->buildResultVar(NULL
, rs
->exp
->type
);
2709 bool r
= fd
->vresult
->checkNestedReference(sc
, Loc());
2710 assert(!r
); // vresult should be always accessible
2712 // Send out "case receiver" statement to the foreach.
2714 Statement
*s
= new ReturnStatement(Loc(), new VarExp(Loc(), fd
->vresult
));
2715 sc
->fes
->cases
->push(s
);
2717 // Save receiver index for the later rewriting from:
2720 // vresult = exp; retrun caseDim;
2721 rs
->caseDim
= sc
->fes
->cases
->dim
+ 1;
2727 fd
->returns
= new ReturnStatements();
2728 fd
->returns
->push(rs
);
2732 result
= new CompoundStatement(rs
->loc
, new ExpStatement(rs
->loc
, e0
), rs
);
2738 void visit(BreakStatement
*bs
)
2740 //printf("BreakStatement::semantic()\n");
2742 // break Identifier;
2745 bs
->ident
= fixupLabelName(sc
, bs
->ident
);
2747 FuncDeclaration
*thisfunc
= sc
->func
;
2749 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2751 if (scx
->func
!= thisfunc
) // if in enclosing function
2753 if (sc
->fes
) // if this is the body of a foreach
2755 /* Post this statement to the fes, and replace
2756 * it with a return value that caller will put into
2757 * a switch. Caller will figure out where the break
2758 * label actually is.
2759 * Case numbers start with 2, not 0, as 0 is continue
2762 sc
->fes
->cases
->push(bs
);
2763 result
= new ReturnStatement(Loc(), new IntegerExp(sc
->fes
->cases
->dim
+ 1));
2766 break; // can't break to it
2769 LabelStatement
*ls
= scx
->slabel
;
2770 if (ls
&& ls
->ident
== bs
->ident
)
2772 Statement
*s
= ls
->statement
;
2774 if (!s
|| !s
->hasBreak())
2775 bs
->error("label '%s' has no break", bs
->ident
->toChars());
2776 else if (ls
->tf
!= sc
->tf
)
2777 bs
->error("cannot break out of finally block");
2787 bs
->error("enclosing label '%s' for break not found", bs
->ident
->toChars());
2790 else if (!sc
->sbreak
)
2792 if (sc
->os
&& sc
->os
->tok
!= TOKon_scope_failure
)
2794 bs
->error("break is not inside %s bodies", Token::toChars(sc
->os
->tok
));
2798 // Replace break; with return 1;
2799 result
= new ReturnStatement(Loc(), new IntegerExp(1));
2803 bs
->error("break is not inside a loop or switch");
2809 void visit(ContinueStatement
*cs
)
2811 //printf("ContinueStatement::semantic() %p\n", cs);
2814 cs
->ident
= fixupLabelName(sc
, cs
->ident
);
2817 FuncDeclaration
*thisfunc
= sc
->func
;
2819 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
2823 if (scx
->func
!= thisfunc
) // if in enclosing function
2825 if (sc
->fes
) // if this is the body of a foreach
2827 for (; scx
; scx
= scx
->enclosing
)
2830 if (ls
&& ls
->ident
== cs
->ident
&& ls
->statement
== sc
->fes
)
2832 // Replace continue ident; with return 0;
2833 result
= new ReturnStatement(Loc(), new IntegerExp(0));
2838 /* Post this statement to the fes, and replace
2839 * it with a return value that caller will put into
2840 * a switch. Caller will figure out where the break
2841 * label actually is.
2842 * Case numbers start with 2, not 0, as 0 is continue
2845 sc
->fes
->cases
->push(cs
);
2846 result
= new ReturnStatement(Loc(), new IntegerExp(sc
->fes
->cases
->dim
+ 1));
2849 break; // can't continue to it
2853 if (ls
&& ls
->ident
== cs
->ident
)
2855 Statement
*s
= ls
->statement
;
2857 if (!s
|| !s
->hasContinue())
2858 cs
->error("label '%s' has no continue", cs
->ident
->toChars());
2859 else if (ls
->tf
!= sc
->tf
)
2860 cs
->error("cannot continue out of finally block");
2869 cs
->error("enclosing label '%s' for continue not found", cs
->ident
->toChars());
2872 else if (!sc
->scontinue
)
2874 if (sc
->os
&& sc
->os
->tok
!= TOKon_scope_failure
)
2876 cs
->error("continue is not inside %s bodies", Token::toChars(sc
->os
->tok
));
2880 // Replace continue; with return 0;
2881 result
= new ReturnStatement(Loc(), new IntegerExp(0));
2885 cs
->error("continue is not inside a loop");
2891 void visit(SynchronizedStatement
*ss
)
2895 ss
->exp
= semantic(ss
->exp
, sc
);
2896 ss
->exp
= resolveProperties(sc
, ss
->exp
);
2897 ss
->exp
= ss
->exp
->optimize(WANTvalue
);
2898 ss
->exp
= checkGC(sc
, ss
->exp
);
2899 if (ss
->exp
->op
== TOKerror
)
2901 ClassDeclaration
*cd
= ss
->exp
->type
->isClassHandle();
2904 ss
->error("can only synchronize on class objects, not '%s'", ss
->exp
->type
->toChars());
2907 else if (cd
->isInterfaceDeclaration())
2909 /* Cast the interface to an object, as the object has the monitor,
2910 * not the interface.
2912 if (!ClassDeclaration::object
)
2914 ss
->error("missing or corrupt object.d");
2918 Type
*t
= ClassDeclaration::object
->type
;
2919 t
= t
->semantic(Loc(), sc
)->toBasetype();
2920 assert(t
->ty
== Tclass
);
2922 ss
->exp
= new CastExp(ss
->loc
, ss
->exp
, t
);
2923 ss
->exp
= semantic(ss
->exp
, sc
);
2928 * _d_monitorenter(tmp);
2929 * try { body } finally { _d_monitorexit(tmp); }
2931 VarDeclaration
*tmp
= copyToTemp(0, "__sync", ss
->exp
);
2933 Statements
*cs
= new Statements();
2934 cs
->push(new ExpStatement(ss
->loc
, tmp
));
2936 Parameters
* args
= new Parameters
;
2937 args
->push(new Parameter(0, ClassDeclaration::object
->type
, NULL
, NULL
));
2939 FuncDeclaration
*fdenter
= FuncDeclaration::genCfunc(args
, Type::tvoid
, Id::monitorenter
);
2940 Expression
*e
= new CallExp(ss
->loc
, new VarExp(ss
->loc
, fdenter
, false), new VarExp(ss
->loc
, tmp
));
2941 e
->type
= Type::tvoid
; // do not run semantic on e
2942 cs
->push(new ExpStatement(ss
->loc
, e
));
2944 FuncDeclaration
*fdexit
= FuncDeclaration::genCfunc(args
, Type::tvoid
, Id::monitorexit
);
2945 e
= new CallExp(ss
->loc
, new VarExp(ss
->loc
, fdexit
, false), new VarExp(ss
->loc
, tmp
));
2946 e
->type
= Type::tvoid
; // do not run semantic on e
2947 Statement
*s
= new ExpStatement(ss
->loc
, e
);
2948 s
= new TryFinallyStatement(ss
->loc
, ss
->_body
, s
);
2951 s
= new CompoundStatement(ss
->loc
, cs
);
2952 result
= semantic(s
, sc
);
2957 /* Generate our own critical section, then rewrite as:
2958 * __gshared byte[CriticalSection.sizeof] critsec;
2959 * _d_criticalenter(critsec.ptr);
2960 * try { body } finally { _d_criticalexit(critsec.ptr); }
2962 Identifier
*id
= Identifier::generateId("__critsec");
2963 Type
*t
= Type::tint8
->sarrayOf(Target::ptrsize
+ Target::critsecsize());
2964 VarDeclaration
*tmp
= new VarDeclaration(ss
->loc
, t
, id
, NULL
);
2965 tmp
->storage_class
|= STCtemp
| STCgshared
| STCstatic
;
2967 Statements
*cs
= new Statements();
2968 cs
->push(new ExpStatement(ss
->loc
, tmp
));
2970 /* This is just a dummy variable for "goto skips declaration" error.
2971 * Backend optimizer could remove this unused variable.
2973 VarDeclaration
*v
= new VarDeclaration(ss
->loc
, Type::tvoidptr
, Identifier::generateId("__sync"), NULL
);
2975 cs
->push(new ExpStatement(ss
->loc
, v
));
2977 Parameters
* args
= new Parameters
;
2978 args
->push(new Parameter(0, t
->pointerTo(), NULL
, NULL
));
2980 FuncDeclaration
*fdenter
= FuncDeclaration::genCfunc(args
, Type::tvoid
, Id::criticalenter
, STCnothrow
);
2981 Expression
*e
= new DotIdExp(ss
->loc
, new VarExp(ss
->loc
, tmp
), Id::ptr
);
2982 e
= semantic(e
, sc
);
2983 e
= new CallExp(ss
->loc
, new VarExp(ss
->loc
, fdenter
, false), e
);
2984 e
->type
= Type::tvoid
; // do not run semantic on e
2985 cs
->push(new ExpStatement(ss
->loc
, e
));
2987 FuncDeclaration
*fdexit
= FuncDeclaration::genCfunc(args
, Type::tvoid
, Id::criticalexit
, STCnothrow
);
2988 e
= new DotIdExp(ss
->loc
, new VarExp(ss
->loc
, tmp
), Id::ptr
);
2989 e
= semantic(e
, sc
);
2990 e
= new CallExp(ss
->loc
, new VarExp(ss
->loc
, fdexit
, false), e
);
2991 e
->type
= Type::tvoid
; // do not run semantic on e
2992 Statement
*s
= new ExpStatement(ss
->loc
, e
);
2993 s
= new TryFinallyStatement(ss
->loc
, ss
->_body
, s
);
2996 s
= new CompoundStatement(ss
->loc
, cs
);
2997 result
= semantic(s
, sc
);
3002 ss
->_body
= semantic(ss
->_body
, sc
);
3003 if (ss
->_body
&& ss
->_body
->isErrorStatement())
3011 void visit(WithStatement
*ws
)
3016 //printf("WithStatement::semantic()\n");
3017 ws
->exp
= semantic(ws
->exp
, sc
);
3018 ws
->exp
= resolveProperties(sc
, ws
->exp
);
3019 ws
->exp
= ws
->exp
->optimize(WANTvalue
);
3020 ws
->exp
= checkGC(sc
, ws
->exp
);
3021 if (ws
->exp
->op
== TOKerror
)
3023 if (ws
->exp
->op
== TOKscope
)
3025 sym
= new WithScopeSymbol(ws
);
3026 sym
->parent
= sc
->scopesym
;
3027 sym
->endlinnum
= ws
->endloc
.linnum
;
3029 else if (ws
->exp
->op
== TOKtype
)
3031 Dsymbol
*s
= ((TypeExp
*)ws
->exp
)->type
->toDsymbol(sc
);
3032 if (!s
|| !s
->isScopeDsymbol())
3034 ws
->error("with type %s has no members", ws
->exp
->toChars());
3037 sym
= new WithScopeSymbol(ws
);
3038 sym
->parent
= sc
->scopesym
;
3039 sym
->endlinnum
= ws
->endloc
.linnum
;
3043 Type
*t
= ws
->exp
->type
->toBasetype();
3045 Expression
*olde
= ws
->exp
;
3046 if (t
->ty
== Tpointer
)
3048 ws
->exp
= new PtrExp(ws
->loc
, ws
->exp
);
3049 ws
->exp
= semantic(ws
->exp
, sc
);
3050 t
= ws
->exp
->type
->toBasetype();
3054 t
= t
->toBasetype();
3055 if (t
->isClassHandle())
3057 init
= new ExpInitializer(ws
->loc
, ws
->exp
);
3058 ws
->wthis
= new VarDeclaration(ws
->loc
, ws
->exp
->type
, Id::withSym
, init
);
3059 ws
->wthis
->semantic(sc
);
3061 sym
= new WithScopeSymbol(ws
);
3062 sym
->parent
= sc
->scopesym
;
3063 sym
->endlinnum
= ws
->endloc
.linnum
;
3065 else if (t
->ty
== Tstruct
)
3067 if (!ws
->exp
->isLvalue())
3071 * auto __withtmp = exp
3078 VarDeclaration
*tmp
= copyToTemp(0, "__withtmp", ws
->exp
);
3079 ExpStatement
*es
= new ExpStatement(ws
->loc
, tmp
);
3080 ws
->exp
= new VarExp(ws
->loc
, tmp
);
3081 Statement
*ss
= new ScopeStatement(ws
->loc
, new CompoundStatement(ws
->loc
, es
, ws
), ws
->endloc
);
3082 result
= semantic(ss
, sc
);
3085 Expression
*e
= ws
->exp
->addressOf();
3086 init
= new ExpInitializer(ws
->loc
, e
);
3087 ws
->wthis
= new VarDeclaration(ws
->loc
, e
->type
, Id::withSym
, init
);
3088 ws
->wthis
->semantic(sc
);
3089 sym
= new WithScopeSymbol(ws
);
3090 // Need to set the scope to make use of resolveAliasThis
3092 sym
->parent
= sc
->scopesym
;
3093 sym
->endlinnum
= ws
->endloc
.linnum
;
3097 ws
->error("with expressions must be aggregate types or pointers to them, not '%s'", olde
->type
->toChars());
3107 ws
->_body
= semantic(ws
->_body
, sc
);
3109 if (ws
->_body
&& ws
->_body
->isErrorStatement())
3119 void visit(TryCatchStatement
*tcs
)
3122 const unsigned FLAGcpp
= 1;
3123 const unsigned FLAGd
= 2;
3125 tcs
->_body
= semanticScope(tcs
->_body
, sc
, NULL
, NULL
);
3128 /* Even if body is empty, still do semantic analysis on catches
3130 bool catchErrors
= false;
3131 for (size_t i
= 0; i
< tcs
->catches
->dim
; i
++)
3133 Catch
*c
= (*tcs
->catches
)[i
];
3140 ClassDeclaration
*cd
= c
->type
->toBasetype()->isClassHandle();
3141 flags
|= cd
->isCPPclass() ? FLAGcpp
: FLAGd
;
3143 // Determine if current catch 'hides' any previous catches
3144 for (size_t j
= 0; j
< i
; j
++)
3146 Catch
*cj
= (*tcs
->catches
)[j
];
3147 const char *si
= c
->loc
.toChars();
3148 const char *sj
= cj
->loc
.toChars();
3150 if (c
->type
->toBasetype()->implicitConvTo(cj
->type
->toBasetype()))
3152 tcs
->error("catch at %s hides catch at %s", sj
, si
);
3160 if (flags
== (FLAGcpp
| FLAGd
))
3162 tcs
->error("cannot mix catching D and C++ exceptions in the same try-catch");
3170 if (tcs
->_body
->isErrorStatement())
3172 result
= tcs
->_body
;
3176 /* If the try body never throws, we can eliminate any catches
3177 * of recoverable exceptions.
3180 if (!(blockExit(tcs
->_body
, sc
->func
, false) & BEthrow
) && ClassDeclaration::exception
)
3182 for (size_t i
= 0; i
< tcs
->catches
->dim
; i
++)
3184 Catch
*c
= (*tcs
->catches
)[i
];
3186 /* If catch exception type is derived from Exception
3188 if (c
->type
->toBasetype()->implicitConvTo(ClassDeclaration::exception
->type
) &&
3189 (!c
->handler
|| !c
->handler
->comeFrom()))
3191 // Remove c from the array of catches
3192 tcs
->catches
->remove(i
);
3198 if (tcs
->catches
->dim
== 0)
3200 result
= tcs
->_body
->hasCode() ? tcs
->_body
: NULL
;
3207 void visit(TryFinallyStatement
*tfs
)
3209 //printf("TryFinallyStatement::semantic()\n");
3210 tfs
->_body
= semantic(tfs
->_body
, sc
);
3214 sc
->scontinue
= NULL
; // no break or continue out of finally block
3215 tfs
->finalbody
= semanticNoScope(tfs
->finalbody
, sc
);
3220 result
= tfs
->finalbody
;
3224 if (!tfs
->finalbody
)
3226 result
= tfs
->_body
;
3230 if (blockExit(tfs
->_body
, sc
->func
, false) == BEfallthru
)
3232 result
= new CompoundStatement(tfs
->loc
, tfs
->_body
, tfs
->finalbody
);
3238 void visit(OnScopeStatement
*oss
)
3241 if (oss
->tok
!= TOKon_scope_exit
)
3243 // scope(success) and scope(failure) are rewritten to try-catch(-finally) statement,
3244 // so the generated catch block cannot be placed in finally block.
3245 // See also Catch::semantic.
3246 if (sc
->os
&& sc
->os
->tok
!= TOKon_scope_failure
)
3248 // If enclosing is scope(success) or scope(exit), this will be placed in finally block.
3249 oss
->error("cannot put %s statement inside %s", Token::toChars(oss
->tok
), Token::toChars(sc
->os
->tok
));
3254 oss
->error("cannot put %s statement inside finally block", Token::toChars(oss
->tok
));
3263 if (oss
->tok
!= TOKon_scope_failure
)
3265 // Jump out from scope(failure) block is allowed.
3267 sc
->scontinue
= NULL
;
3269 oss
->statement
= semanticNoScope(oss
->statement
, sc
);
3272 if (!oss
->statement
|| oss
->statement
->isErrorStatement())
3274 result
= oss
->statement
;
3280 void visit(ThrowStatement
*ts
)
3282 //printf("ThrowStatement::semantic()\n");
3284 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3285 fd
->hasReturnExp
|= 2;
3287 ts
->exp
= semantic(ts
->exp
, sc
);
3288 ts
->exp
= resolveProperties(sc
, ts
->exp
);
3289 ts
->exp
= checkGC(sc
, ts
->exp
);
3290 if (ts
->exp
->op
== TOKerror
)
3293 checkThrowEscape(sc
, ts
->exp
, false);
3295 ClassDeclaration
*cd
= ts
->exp
->type
->toBasetype()->isClassHandle();
3296 if (!cd
|| ((cd
!= ClassDeclaration::throwable
) && !ClassDeclaration::throwable
->isBaseOf(cd
, NULL
)))
3298 ts
->error("can only throw class objects derived from Throwable, not type %s", ts
->exp
->type
->toChars());
3305 void visit(DebugStatement
*ds
)
3310 sc
->flags
|= SCOPEdebug
;
3311 ds
->statement
= semantic(ds
->statement
, sc
);
3314 result
= ds
->statement
;
3317 void visit(GotoStatement
*gs
)
3319 //printf("GotoStatement::semantic()\n");
3320 FuncDeclaration
*fd
= sc
->func
;
3322 gs
->ident
= fixupLabelName(sc
, gs
->ident
);
3323 gs
->label
= fd
->searchLabel(gs
->ident
);
3326 gs
->lastVar
= sc
->lastVar
;
3328 if (!gs
->label
->statement
&& sc
->fes
)
3330 /* Either the goto label is forward referenced or it
3331 * is in the function that the enclosing foreach is in.
3332 * Can't know yet, so wrap the goto in a scope statement
3333 * so we can patch it later, and add it to a 'look at this later'
3336 ScopeStatement
*ss
= new ScopeStatement(gs
->loc
, gs
, gs
->loc
);
3337 sc
->fes
->gotos
->push(ss
); // 'look at this later' list
3342 // Add to fwdref list to check later
3343 if (!gs
->label
->statement
)
3346 fd
->gotos
= new GotoStatements();
3347 fd
->gotos
->push(gs
);
3349 else if (gs
->checkLabel())
3355 void visit(LabelStatement
*ls
)
3357 //printf("LabelStatement::semantic()\n");
3358 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3360 ls
->ident
= fixupLabelName(sc
, ls
->ident
);
3363 ls
->lastVar
= sc
->lastVar
;
3365 LabelDsymbol
*ls2
= fd
->searchLabel(ls
->ident
);
3368 ls
->error("label '%s' already defined", ls2
->toChars());
3372 ls2
->statement
= ls
;
3375 sc
->scopesym
= sc
->enclosing
->scopesym
;
3376 sc
->callSuper
|= CSXlabel
;
3379 size_t dim
= sc
->fieldinit_dim
;
3380 for (size_t i
= 0; i
< dim
; i
++)
3381 sc
->fieldinit
[i
] |= CSXlabel
;
3385 ls
->statement
= semantic(ls
->statement
, sc
);
3391 void visit(AsmStatement
*s
)
3393 result
= asmSemantic(s
, sc
);
3396 void visit(CompoundAsmStatement
*cas
)
3398 // Apply postfix attributes of the asm block to each statement.
3400 sc
->stc
|= cas
->stc
;
3402 for (size_t i
= 0; i
< cas
->statements
->dim
; i
++)
3404 Statement
*s
= (*cas
->statements
)[i
];
3405 (*cas
->statements
)[i
] = s
? semantic(s
, sc
) : NULL
;
3409 // use setImpure/setGC when the deprecation cycle is over
3411 if (!(cas
->stc
& STCpure
) && (purity
= sc
->func
->isPureBypassingInference()) != PUREimpure
&& purity
!= PUREfwdref
)
3412 cas
->deprecation("asm statement is assumed to be impure - mark it with 'pure' if it is not");
3413 if (!(cas
->stc
& STCnogc
) && sc
->func
->isNogcBypassingInference())
3414 cas
->deprecation("asm statement is assumed to use the GC - mark it with '@nogc' if it does not");
3415 if (!(cas
->stc
& (STCtrusted
|STCsafe
)) && sc
->func
->setUnsafe())
3416 cas
->error("asm statement is assumed to be @system - mark it with '@trusted' if it is not");
3422 void visit(ImportStatement
*imps
)
3424 for (size_t i
= 0; i
< imps
->imports
->dim
; i
++)
3426 Import
*s
= (*imps
->imports
)[i
]->isImport();
3427 assert(!s
->aliasdecls
.dim
);
3428 for (size_t j
= 0; j
< s
->names
.dim
; j
++)
3430 Identifier
*name
= s
->names
[j
];
3431 Identifier
*alias
= s
->aliases
[j
];
3436 TypeIdentifier
*tname
= new TypeIdentifier(s
->loc
, name
);
3437 AliasDeclaration
*ad
= new AliasDeclaration(s
->loc
, alias
, tname
);
3439 s
->aliasdecls
.push(ad
);
3443 Module::addDeferredSemantic2(s
); // Bugzilla 14666
3446 for (size_t j
= 0; j
< s
->aliasdecls
.dim
; j
++)
3448 sc
->insert(s
->aliasdecls
[j
]);
3455 Statement
*semantic(Statement
*s
, Scope
*sc
)
3457 StatementSemanticVisitor v
= StatementSemanticVisitor(sc
);
3462 void semantic(Catch
*c
, Scope
*sc
)
3464 //printf("Catch::semantic(%s)\n", ident->toChars());
3467 if (sc
->os
&& sc
->os
->tok
!= TOKon_scope_failure
)
3469 // If enclosing is scope(success) or scope(exit), this will be placed in finally block.
3470 error(c
->loc
, "cannot put catch statement inside %s", Token::toChars(sc
->os
->tok
));
3475 /* This is because the _d_local_unwind() gets the stack munged
3476 * up on this. The workaround is to place any try-catches into
3477 * a separate function, and call that.
3478 * To fix, have the compiler automatically convert the finally
3479 * body into a nested function.
3481 error(c
->loc
, "cannot put catch statement inside finally block");
3486 ScopeDsymbol
*sym
= new ScopeDsymbol();
3487 sym
->parent
= sc
->scopesym
;
3492 deprecation(c
->loc
, "catch statement without an exception specification is deprecated; use catch(Throwable) for old behavior");
3494 // reference .object.Throwable
3495 c
->type
= getThrowable();
3497 c
->type
= c
->type
->semantic(c
->loc
, sc
);
3498 if (c
->type
== Type::terror
)
3502 ClassDeclaration
*cd
= c
->type
->toBasetype()->isClassHandle();
3505 error(c
->loc
, "can only catch class objects, not '%s'", c
->type
->toChars());
3508 else if (cd
->isCPPclass())
3510 if (!Target::cppExceptions
)
3512 error(c
->loc
, "catching C++ class objects not supported for this target");
3515 if (sc
->func
&& !sc
->intypeof
&& !c
->internalCatch
&& sc
->func
->setUnsafe())
3517 error(c
->loc
, "cannot catch C++ class objects in @safe code");
3521 else if (cd
!= ClassDeclaration::throwable
&& !ClassDeclaration::throwable
->isBaseOf(cd
, NULL
))
3523 error(c
->loc
, "can only catch class objects derived from Throwable, not '%s'", c
->type
->toChars());
3526 else if (sc
->func
&& !sc
->intypeof
&& !c
->internalCatch
&&
3527 cd
!= ClassDeclaration::exception
&& !ClassDeclaration::exception
->isBaseOf(cd
, NULL
) &&
3528 sc
->func
->setUnsafe())
3530 error(c
->loc
, "can only catch class objects derived from Exception in @safe code, not '%s'", c
->type
->toChars());
3536 c
->var
= new VarDeclaration(c
->loc
, c
->type
, c
->ident
, NULL
);
3537 c
->var
->semantic(sc
);
3540 c
->handler
= semantic(c
->handler
, sc
);
3541 if (c
->handler
&& c
->handler
->isErrorStatement())
3547 Statement
*semanticNoScope(Statement
*s
, Scope
*sc
)
3549 //printf("Statement::semanticNoScope() %s\n", toChars());
3550 if (!s
->isCompoundStatement() && !s
->isScopeStatement())
3552 s
= new CompoundStatement(s
->loc
, s
); // so scopeCode() gets called
3554 s
= semantic(s
, sc
);
3558 // Same as semanticNoScope(), but do create a new scope
3559 Statement
*semanticScope(Statement
*s
, Scope
*sc
, Statement
*sbreak
, Statement
*scontinue
)
3561 ScopeDsymbol
*sym
= new ScopeDsymbol();
3562 sym
->parent
= sc
->scopesym
;
3563 Scope
*scd
= sc
->push(sym
);
3565 scd
->sbreak
= sbreak
;
3567 scd
->scontinue
= scontinue
;
3568 s
= semanticNoScope(s
, scd
);