1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2021 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 */
9
10 #include "dsymbol.h"
11 #include "aggregate.h"
12 #include "attrib.h"
13 #include "declaration.h"
14 #include "errors.h"
15 #include "id.h"
16 #include "init.h"
17 #include "module.h"
18 #include "nspace.h"
19 #include "scope.h"
20 #include "statement.h"
21 #include "statement_rewrite_walker.h"
22 #include "target.h"
23 #include "template.h"
24 #include "visitor.h"
25
26 bool allowsContractWithoutBody(FuncDeclaration *funcdecl);
27 int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
28 bool checkReturnEscape(Scope *sc, Expression *e, bool gag);
29 bool checkReturnEscapeRef(Scope *sc, Expression *e, bool gag);
30 TypeIdentifier *getThrowable();
31 char *MODtoChars(MOD mod);
32 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
33 void allocFieldinit(Scope *sc, size_t dim);
34 void freeFieldinit(Scope *sc);
35
36 /* Determine if function should add `return 0;`
37 */
addReturn0(FuncDeclaration * funcdecl)38 static bool addReturn0(FuncDeclaration *funcdecl)
39 {
40 TypeFunction *f = (TypeFunction *)funcdecl->type;
41
42 return f->next->ty == Tvoid &&
43 (funcdecl->isMain() || (global.params.betterC && funcdecl->isCMain()));
44 }
45
46 /********************************************************
47 * Generate Expression to call the invariant.
48 * Input:
49 * ad aggregate with the invariant
50 * vthis variable with 'this'
51 * Returns:
52 * void expression that calls the invariant
53 */
addInvariant(AggregateDeclaration * ad,VarDeclaration * vthis)54 static Expression *addInvariant(AggregateDeclaration *ad, VarDeclaration *vthis)
55 {
56 Expression *e = NULL;
57
58 // Call invariant directly only if it exists
59 FuncDeclaration *inv = ad->inv;
60 ClassDeclaration *cd = ad->isClassDeclaration();
61
62 while (!inv && cd)
63 {
64 cd = cd->baseClass;
65 if (!cd)
66 break;
67 inv = cd->inv;
68 }
69 if (inv)
70 {
71 #if 1
72 // Workaround for bugzilla 13394: For the correct mangling,
73 // run attribute inference on inv if needed.
74 inv->functionSemantic();
75 #endif
76
77 //e = new DsymbolExp(Loc(), inv);
78 //e = new CallExp(Loc(), e);
79 //dsymbolSemantic(e, sc2);
80
81 /* https://issues.dlang.org/show_bug.cgi?id=13113
82 * Currently virtual invariant calls completely
83 * bypass attribute enforcement.
84 * Change the behavior of pre-invariant call by following it.
85 */
86 e = new ThisExp(Loc());
87 e->type = vthis->type;
88 e = new DotVarExp(Loc(), e, inv, false);
89 e->type = inv->type;
90 e = new CallExp(Loc(), e);
91 e->type = Type::tvoid;
92 }
93 return e;
94 }
95
96 /* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
97 */
98 class NrvoWalker : public StatementRewriteWalker
99 {
100 public:
101 FuncDeclaration *fd;
102 Scope *sc;
103
visit(ReturnStatement * s)104 void visit(ReturnStatement *s)
105 {
106 // See if all returns are instead to be replaced with a goto returnLabel;
107 if (fd->returnLabel)
108 {
109 /* Rewrite:
110 * return exp;
111 * as:
112 * vresult = exp; goto Lresult;
113 */
114 GotoStatement *gs = new GotoStatement(s->loc, Id::returnLabel);
115 gs->label = fd->returnLabel;
116
117 Statement *s1 = gs;
118 if (s->exp)
119 s1 = new CompoundStatement(s->loc, new ExpStatement(s->loc, s->exp), gs);
120
121 replaceCurrent(s1);
122 }
123 }
visit(TryFinallyStatement * s)124 void visit(TryFinallyStatement *s)
125 {
126 DtorExpStatement *des;
127 if (fd->nrvo_can &&
128 s->finalbody && (des = s->finalbody->isDtorExpStatement()) != NULL &&
129 fd->nrvo_var == des->var)
130 {
131 if (!(global.params.useExceptions && ClassDeclaration::throwable))
132 {
133 /* Don't need to call destructor at all, since it is nrvo
134 */
135 replaceCurrent(s->_body);
136 s->_body->accept(this);
137 return;
138 }
139
140 /* Normally local variable dtors are called regardless exceptions.
141 * But for nrvo_var, its dtor should be called only when exception is thrown.
142 *
143 * Rewrite:
144 * try { s->body; } finally { nrvo_var->edtor; }
145 * // equivalent with:
146 * // s->body; scope(exit) nrvo_var->edtor;
147 * as:
148 * try { s->body; } catch(Throwable __o) { nrvo_var->edtor; throw __o; }
149 * // equivalent with:
150 * // s->body; scope(failure) nrvo_var->edtor;
151 */
152 Statement *sexception = new DtorExpStatement(Loc(), fd->nrvo_var->edtor, fd->nrvo_var);
153 Identifier *id = Identifier::generateId("__o");
154
155 Statement *handler = new PeelStatement(sexception);
156 if (blockExit(sexception, fd, false) & BEfallthru)
157 {
158 ThrowStatement *ts = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id));
159 ts->internalThrow = true;
160 handler = new CompoundStatement(Loc(), handler, ts);
161 }
162
163 Catches *catches = new Catches();
164 Catch *ctch = new Catch(Loc(), getThrowable(), id, handler);
165 ctch->internalCatch = true;
166 catchSemantic(ctch, sc); // Run semantic to resolve identifier '__o'
167 catches->push(ctch);
168
169 Statement *s2 = new TryCatchStatement(Loc(), s->_body, catches);
170 replaceCurrent(s2);
171 s2->accept(this);
172 }
173 else
174 StatementRewriteWalker::visit(s);
175 }
176 };
177
178 class Semantic3Visitor : public Visitor
179 {
180 public:
181 Scope *sc;
182
Semantic3Visitor(Scope * sc)183 Semantic3Visitor(Scope *sc)
184 {
185 this->sc = sc;
186 }
187
visit(Dsymbol *)188 void visit(Dsymbol *)
189 {
190 // Most Dsymbols have no further semantic analysis needed
191 }
192
visit(TemplateInstance * tempinst)193 void visit(TemplateInstance *tempinst)
194 {
195 //if (tempinst->toChars()[0] == 'D') *(char*)0=0;
196 if (tempinst->semanticRun >= PASSsemantic3)
197 return;
198 tempinst->semanticRun = PASSsemantic3;
199 if (!tempinst->errors && tempinst->members)
200 {
201 TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration();
202 assert(tempdecl);
203
204 sc = tempdecl->_scope;
205 sc = sc->push(tempinst->argsym);
206 sc = sc->push(tempinst);
207 sc->tinst = tempinst;
208 sc->minst = tempinst->minst;
209
210 int needGagging = (tempinst->gagged && !global.gag);
211 unsigned int olderrors = global.errors;
212 int oldGaggedErrors = -1; // dead-store to prevent spurious warning
213 /* If this is a gagged instantiation, gag errors.
214 * Future optimisation: If the results are actually needed, errors
215 * would already be gagged, so we don't really need to run semantic
216 * on the members.
217 */
218 if (needGagging)
219 oldGaggedErrors = global.startGagging();
220
221 for (size_t i = 0; i < tempinst->members->length; i++)
222 {
223 Dsymbol *s = (*tempinst->members)[i];
224 semantic3(s, sc);
225 if (tempinst->gagged && global.errors != olderrors)
226 break;
227 }
228
229 if (global.errors != olderrors)
230 {
231 if (!tempinst->errors)
232 {
233 if (!tempdecl->literal)
234 tempinst->error(tempinst->loc, "error instantiating");
235 if (tempinst->tinst)
236 tempinst->tinst->printInstantiationTrace();
237 }
238 tempinst->errors = true;
239 }
240 if (needGagging)
241 global.endGagging(oldGaggedErrors);
242
243 sc = sc->pop();
244 sc->pop();
245 }
246 }
247
visit(TemplateMixin * tmix)248 void visit(TemplateMixin *tmix)
249 {
250 if (tmix->semanticRun >= PASSsemantic3)
251 return;
252 tmix->semanticRun = PASSsemantic3;
253 if (tmix->members)
254 {
255 sc = sc->push(tmix->argsym);
256 sc = sc->push(tmix);
257 for (size_t i = 0; i < tmix->members->length; i++)
258 {
259 Dsymbol *s = (*tmix->members)[i];
260 semantic3(s, sc);
261 }
262 sc = sc->pop();
263 sc->pop();
264 }
265 }
266
visit(Module * mod)267 void visit(Module *mod)
268 {
269 //printf("Module::semantic3('%s'): parent = %p\n", mod->toChars(), mod->parent);
270 if (mod->semanticRun != PASSsemantic2done)
271 return;
272 mod->semanticRun = PASSsemantic3;
273
274 // Note that modules get their own scope, from scratch.
275 // This is so regardless of where in the syntax a module
276 // gets imported, it is unaffected by context.
277 Scope *sc = Scope::createGlobal(mod); // create root scope
278 //printf("Module = %p\n", sc.scopesym);
279
280 // Pass 3 semantic routines: do initializers and function bodies
281 for (size_t i = 0; i < mod->members->length; i++)
282 {
283 Dsymbol *s = (*mod->members)[i];
284 //printf("Module %s: %s.semantic3()\n", mod->toChars(), s->toChars());
285 semantic3(s, sc);
286
287 mod->runDeferredSemantic2();
288 }
289
290 if (mod->userAttribDecl)
291 {
292 semantic3(mod->userAttribDecl, sc);
293 }
294
295 sc = sc->pop();
296 sc->pop();
297 mod->semanticRun = PASSsemantic3done;
298 }
299
visit(FuncDeclaration * funcdecl)300 void visit(FuncDeclaration *funcdecl)
301 {
302 VarDeclaration *_arguments = NULL;
303
304 if (!funcdecl->parent)
305 {
306 if (global.errors)
307 return;
308 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", funcdecl->kind(), funcdecl->toChars(), sc);
309 assert(0);
310 }
311 if (funcdecl->errors || isError(funcdecl->parent))
312 {
313 funcdecl->errors = true;
314 return;
315 }
316 //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", funcdecl->parent->toChars(), funcdecl->toChars(), funcdecl, sc, funcdecl->loc.toChars());
317 //fflush(stdout);
318 //printf("storage class = x%x %x\n", sc->stc, funcdecl->storage_class);
319 //{ static int x; if (++x == 2) *(char*)0=0; }
320 //printf("\tlinkage = %d\n", sc->linkage);
321
322 if (funcdecl->ident == Id::assign && !funcdecl->inuse)
323 {
324 if (funcdecl->storage_class & STCinference)
325 {
326 /* Bugzilla 15044: For generated opAssign function, any errors
327 * from its body need to be gagged.
328 */
329 unsigned oldErrors = global.startGagging();
330 funcdecl->inuse++;
331 semantic3(funcdecl, sc);
332 funcdecl->inuse--;
333 if (global.endGagging(oldErrors)) // if errors happened
334 {
335 // Disable generated opAssign, because some members forbid identity assignment.
336 funcdecl->storage_class |= STCdisable;
337 funcdecl->fbody = NULL; // remove fbody which contains the error
338 funcdecl->semantic3Errors = false;
339 }
340 return;
341 }
342 }
343
344 //printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract));
345 if (funcdecl->semanticRun >= PASSsemantic3)
346 return;
347 funcdecl->semanticRun = PASSsemantic3;
348 funcdecl->semantic3Errors = false;
349
350 if (!funcdecl->type || funcdecl->type->ty != Tfunction)
351 return;
352 TypeFunction *f = (TypeFunction *)funcdecl->type;
353 if (!funcdecl->inferRetType && f->next->ty == Terror)
354 return;
355
356 if (!funcdecl->fbody && funcdecl->inferRetType && !f->next)
357 {
358 funcdecl->error("has no function body with return type inference");
359 return;
360 }
361
362 unsigned oldErrors = global.errors;
363
364 if (funcdecl->frequires)
365 {
366 for (size_t i = 0; i < funcdecl->foverrides.length; i++)
367 {
368 FuncDeclaration *fdv = funcdecl->foverrides[i];
369
370 if (fdv->fbody && !fdv->frequires)
371 {
372 funcdecl->error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars());
373 break;
374 }
375 }
376 }
377
378 // Remember whether we need to generate an 'out' contract.
379 const bool needEnsure = FuncDeclaration::needsFensure(funcdecl);
380
381 if (funcdecl->fbody || funcdecl->frequires || needEnsure)
382 {
383 /* Symbol table into which we place parameters and nested functions,
384 * solely to diagnose name collisions.
385 */
386 funcdecl->localsymtab = new DsymbolTable();
387
388 // Establish function scope
389 ScopeDsymbol *ss = new ScopeDsymbol();
390 // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
391 for (Scope *scx = sc; ; scx = scx->enclosing)
392 {
393 if (scx->scopesym)
394 {
395 ss->parent = scx->scopesym;
396 break;
397 }
398 }
399 ss->loc = funcdecl->loc;
400 ss->endlinnum = funcdecl->endloc.linnum;
401 Scope *sc2 = sc->push(ss);
402 sc2->func = funcdecl;
403 sc2->parent = funcdecl;
404 sc2->callSuper = 0;
405 sc2->sbreak = NULL;
406 sc2->scontinue = NULL;
407 sc2->sw = NULL;
408 sc2->fes = funcdecl->fes;
409 sc2->linkage = LINKd;
410 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCabstract |
411 STCdeprecated | STCoverride |
412 STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | STCreturn |
413 STCproperty | STCnothrow | STCpure | STCsafe | STCtrusted | STCsystem);
414 sc2->protection = Prot(Prot::public_);
415 sc2->explicitProtection = 0;
416 sc2->aligndecl = NULL;
417 if (funcdecl->ident != Id::require && funcdecl->ident != Id::ensure)
418 sc2->flags = sc->flags & ~SCOPEcontract;
419 sc2->flags &= ~SCOPEcompile;
420 sc2->tf = NULL;
421 sc2->os = NULL;
422 sc2->noctor = 0;
423 sc2->userAttribDecl = NULL;
424 if (sc2->intypeof == 1) sc2->intypeof = 2;
425 sc2->fieldinit = NULL;
426 sc2->fieldinit_dim = 0;
427
428 /* Note: When a lambda is defined immediately under aggregate member
429 * scope, it should be contextless due to prevent interior pointers.
430 * e.g.
431 * // dg points 'this' - it's interior pointer
432 * class C { int x; void delegate() dg = (){ this.x = 1; }; }
433 *
434 * However, lambdas could be used inside typeof, in order to check
435 * some expressions varidity at compile time. For such case the lambda
436 * body can access aggregate instance members.
437 * e.g.
438 * class C { int x; static assert(is(typeof({ this.x = 1; }))); }
439 *
440 * To properly accept it, mark these lambdas as member functions.
441 */
442 if (FuncLiteralDeclaration *fld = funcdecl->isFuncLiteralDeclaration())
443 {
444 if (AggregateDeclaration *ad = funcdecl->isMember2())
445 {
446 if (!sc->intypeof)
447 {
448 if (fld->tok == TOKdelegate)
449 funcdecl->error("cannot be %s members", ad->kind());
450 else
451 fld->tok = TOKfunction;
452 }
453 else
454 {
455 if (fld->tok != TOKfunction)
456 fld->tok = TOKdelegate;
457 }
458 }
459 }
460
461 // Declare 'this'
462 AggregateDeclaration *ad = funcdecl->isThis();
463 funcdecl->vthis = funcdecl->declareThis(sc2, ad);
464 //printf("[%s] ad = %p vthis = %p\n", funcdecl->loc.toChars(), ad, funcdecl->vthis);
465 //if (funcdecl->vthis) printf("\tvthis->type = %s\n", funcdecl->vthis->type->toChars());
466
467 // Declare hidden variable _arguments[] and _argptr
468 if (f->parameterList.varargs == VARARGvariadic)
469 {
470 if (f->linkage == LINKd)
471 {
472 // Variadic arguments depend on Typeinfo being defined
473 if (!global.params.useTypeInfo || !Type::dtypeinfo || !Type::typeinfotypelist)
474 {
475 if (!global.params.useTypeInfo)
476 funcdecl->error("D-style variadic functions cannot be used with -betterC");
477 else if (!Type::typeinfotypelist)
478 funcdecl->error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
479 else
480 funcdecl->error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
481 fatal();
482 }
483
484 // Declare _arguments[]
485 funcdecl->v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
486 funcdecl->v_arguments->storage_class |= STCtemp | STCparameter;
487 dsymbolSemantic(funcdecl->v_arguments, sc2);
488 sc2->insert(funcdecl->v_arguments);
489 funcdecl->v_arguments->parent = funcdecl;
490
491 //Type *t = Type::typeinfo->type->constOf()->arrayOf();
492 Type *t = Type::dtypeinfo->type->arrayOf();
493 _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
494 _arguments->storage_class |= STCtemp;
495 dsymbolSemantic(_arguments, sc2);
496 sc2->insert(_arguments);
497 _arguments->parent = funcdecl;
498 }
499 if (f->linkage == LINKd || f->parameterList.length())
500 {
501 // Declare _argptr
502 Type *t = target.va_listType(funcdecl->loc, sc);
503 funcdecl->v_argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
504 funcdecl->v_argptr->storage_class |= STCtemp;
505 dsymbolSemantic(funcdecl->v_argptr, sc2);
506 sc2->insert(funcdecl->v_argptr);
507 funcdecl->v_argptr->parent = funcdecl;
508 }
509 }
510
511 /* Declare all the function parameters as variables
512 * and install them in parameters[]
513 */
514 size_t nparams = f->parameterList.length();
515 if (nparams)
516 {
517 /* parameters[] has all the tuples removed, as the back end
518 * doesn't know about tuples
519 */
520 funcdecl->parameters = new VarDeclarations();
521 funcdecl->parameters->reserve(nparams);
522 for (size_t i = 0; i < nparams; i++)
523 {
524 Parameter *fparam = f->parameterList[i];
525 Identifier *id = fparam->ident;
526 StorageClass stc = 0;
527 if (!id)
528 {
529 /* Generate identifier for un-named parameter,
530 * because we need it later on.
531 */
532 fparam->ident = id = Identifier::generateId("_param_", i);
533 stc |= STCtemp;
534 }
535 Type *vtype = fparam->type;
536 VarDeclaration *v = new VarDeclaration(funcdecl->loc, vtype, id, NULL);
537 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
538 stc |= STCparameter;
539 if (f->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
540 stc |= STCvariadic;
541 if (funcdecl->flags & FUNCFLAGinferScope && !(fparam->storageClass & STCscope))
542 stc |= STCmaybescope;
543 stc |= fparam->storageClass & (STCin | STCout | STCref | STCreturn | STCscope | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
544 v->storage_class = stc;
545 dsymbolSemantic(v, sc2);
546 if (!sc2->insert(v))
547 funcdecl->error("parameter %s.%s is already defined", funcdecl->toChars(), v->toChars());
548 else
549 funcdecl->parameters->push(v);
550 funcdecl->localsymtab->insert(v);
551 v->parent = funcdecl;
552 if (fparam->userAttribDecl)
553 v->userAttribDecl = fparam->userAttribDecl;
554 }
555 }
556
557 // Declare the tuple symbols and put them in the symbol table,
558 // but not in parameters[].
559 if (f->parameterList.parameters)
560 {
561 for (size_t i = 0; i < f->parameterList.parameters->length; i++)
562 {
563 Parameter *fparam = (*f->parameterList.parameters)[i];
564
565 if (!fparam->ident)
566 continue; // never used, so ignore
567 if (fparam->type->ty == Ttuple)
568 {
569 TypeTuple *t = (TypeTuple *)fparam->type;
570 size_t dim = Parameter::dim(t->arguments);
571 Objects *exps = new Objects();
572 exps->setDim(dim);
573 for (size_t j = 0; j < dim; j++)
574 {
575 Parameter *narg = Parameter::getNth(t->arguments, j);
576 assert(narg->ident);
577 VarDeclaration *v = sc2->search(Loc(), narg->ident, NULL)->isVarDeclaration();
578 assert(v);
579 Expression *e = new VarExp(v->loc, v);
580 (*exps)[j] = e;
581 }
582 assert(fparam->ident);
583 TupleDeclaration *v = new TupleDeclaration(funcdecl->loc, fparam->ident, exps);
584 //printf("declaring tuple %s\n", v->toChars());
585 v->isexp = true;
586 if (!sc2->insert(v))
587 funcdecl->error("parameter %s.%s is already defined", funcdecl->toChars(), v->toChars());
588 funcdecl->localsymtab->insert(v);
589 v->parent = funcdecl;
590 }
591 }
592 }
593
594 // Precondition invariant
595 Statement *fpreinv = NULL;
596 if (funcdecl->addPreInvariant())
597 {
598 Expression *e = addInvariant(ad, funcdecl->vthis);
599 if (e)
600 fpreinv = new ExpStatement(Loc(), e);
601 }
602
603 // Postcondition invariant
604 Statement *fpostinv = NULL;
605 if (funcdecl->addPostInvariant())
606 {
607 Expression *e = addInvariant(ad, funcdecl->vthis);
608 if (e)
609 fpostinv = new ExpStatement(Loc(), e);
610 }
611
612 // Pre/Postcondition contract
613 if (!funcdecl->fbody)
614 funcdecl->buildEnsureRequire();
615
616 Scope *scout = NULL;
617 if (needEnsure || funcdecl->addPostInvariant())
618 {
619 if ((needEnsure && global.params.useOut == CHECKENABLEon) || fpostinv)
620 {
621 funcdecl->returnLabel = new LabelDsymbol(Id::returnLabel);
622 }
623
624 // scope of out contract (need for vresult->semantic)
625 ScopeDsymbol *sym = new ScopeDsymbol();
626 sym->parent = sc2->scopesym;
627 sym->loc = funcdecl->loc;
628 sym->endlinnum = funcdecl->endloc.linnum;
629 scout = sc2->push(sym);
630 }
631
632 if (funcdecl->fbody)
633 {
634 ScopeDsymbol *sym = new ScopeDsymbol();
635 sym->parent = sc2->scopesym;
636 sym->loc = funcdecl->loc;
637 sym->endlinnum = funcdecl->endloc.linnum;
638 sc2 = sc2->push(sym);
639
640 AggregateDeclaration *ad2 = funcdecl->isMember2();
641
642 /* If this is a class constructor
643 */
644 if (ad2 && funcdecl->isCtorDeclaration())
645 {
646 allocFieldinit(sc2, ad2->fields.length);
647 for (size_t i = 0; i < ad2->fields.length; i++)
648 {
649 VarDeclaration *v = ad2->fields[i];
650 v->ctorinit = 0;
651 }
652 }
653
654 bool inferRef = (f->isref && (funcdecl->storage_class & STCauto));
655
656 funcdecl->fbody = statementSemantic(funcdecl->fbody, sc2);
657 if (!funcdecl->fbody)
658 funcdecl->fbody = new CompoundStatement(Loc(), new Statements());
659
660 if (funcdecl->naked)
661 {
662 fpreinv = NULL; // can't accommodate with no stack frame
663 fpostinv = NULL;
664 }
665
666 assert(funcdecl->type == f ||
667 (funcdecl->type->ty == Tfunction &&
668 f->purity == PUREimpure &&
669 ((TypeFunction *)funcdecl->type)->purity >= PUREfwdref));
670 f = (TypeFunction *)funcdecl->type;
671
672 if (funcdecl->inferRetType)
673 {
674 // If no return type inferred yet, then infer a void
675 if (!f->next)
676 f->next = Type::tvoid;
677 if (f->checkRetType(funcdecl->loc))
678 funcdecl->fbody = new ErrorStatement();
679 }
680 if (global.params.vcomplex && f->next != NULL)
681 f->next->checkComplexTransition(funcdecl->loc);
682
683 if (funcdecl->returns && !funcdecl->fbody->isErrorStatement())
684 {
685 for (size_t i = 0; i < funcdecl->returns->length; )
686 {
687 Expression *exp = (*funcdecl->returns)[i]->exp;
688 if (exp->op == TOKvar && ((VarExp *)exp)->var == funcdecl->vresult)
689 {
690 if (addReturn0(funcdecl))
691 exp->type = Type::tint32;
692 else
693 exp->type = f->next;
694 // Remove `return vresult;` from returns
695 funcdecl->returns->remove(i);
696 continue;
697 }
698 if (inferRef && f->isref && !exp->type->constConv(f->next)) // Bugzilla 13336
699 f->isref = false;
700 i++;
701 }
702 }
703 if (f->isref) // Function returns a reference
704 {
705 if (funcdecl->storage_class & STCauto)
706 funcdecl->storage_class &= ~STCauto;
707 }
708 if (!target.isReturnOnStack(f, funcdecl->needThis()) || !funcdecl->checkNRVO())
709 funcdecl->nrvo_can = 0;
710
711 if (funcdecl->fbody->isErrorStatement())
712 ;
713 else if (funcdecl->isStaticCtorDeclaration())
714 {
715 /* It's a static constructor. Ensure that all
716 * ctor consts were initialized.
717 */
718 ScopeDsymbol *pd = funcdecl->toParent()->isScopeDsymbol();
719 for (size_t i = 0; i < pd->members->length; i++)
720 {
721 Dsymbol *s = (*pd->members)[i];
722 s->checkCtorConstInit();
723 }
724 }
725 else if (ad2 && funcdecl->isCtorDeclaration())
726 {
727 ClassDeclaration *cd = ad2->isClassDeclaration();
728
729 // Verify that all the ctorinit fields got initialized
730 if (!(sc2->callSuper & CSXthis_ctor))
731 {
732 for (size_t i = 0; i < ad2->fields.length; i++)
733 {
734 VarDeclaration *v = ad2->fields[i];
735 if (v->isThisDeclaration())
736 continue;
737 if (v->ctorinit == 0)
738 {
739 /* Current bugs in the flow analysis:
740 * 1. union members should not produce error messages even if
741 * not assigned to
742 * 2. structs should recognize delegating opAssign calls as well
743 * as delegating calls to other constructors
744 */
745 if (v->isCtorinit() && !v->type->isMutable() && cd)
746 funcdecl->error("missing initializer for %s field %s", MODtoChars(v->type->mod), v->toChars());
747 else if (v->storage_class & STCnodefaultctor)
748 error(funcdecl->loc, "field %s must be initialized in constructor", v->toChars());
749 else if (v->type->needsNested())
750 error(funcdecl->loc, "field %s must be initialized in constructor, because it is nested struct", v->toChars());
751 }
752 else
753 {
754 bool mustInit = (v->storage_class & STCnodefaultctor ||
755 v->type->needsNested());
756 if (mustInit && !(sc2->fieldinit[i] & CSXthis_ctor))
757 {
758 funcdecl->error("field %s must be initialized but skipped", v->toChars());
759 }
760 }
761 }
762 }
763 freeFieldinit(sc2);
764
765 if (cd &&
766 !(sc2->callSuper & CSXany_ctor) &&
767 cd->baseClass && cd->baseClass->ctor)
768 {
769 sc2->callSuper = 0;
770
771 // Insert implicit super() at start of fbody
772 FuncDeclaration *fd = resolveFuncCall(Loc(), sc2, cd->baseClass->ctor, NULL, funcdecl->vthis->type, NULL, 1);
773 if (!fd)
774 {
775 funcdecl->error("no match for implicit super() call in constructor");
776 }
777 else if (fd->storage_class & STCdisable)
778 {
779 funcdecl->error("cannot call super() implicitly because it is annotated with @disable");
780 }
781 else
782 {
783 Expression *e1 = new SuperExp(Loc());
784 Expression *e = new CallExp(Loc(), e1);
785 e = expressionSemantic(e, sc2);
786
787 Statement *s = new ExpStatement(Loc(), e);
788 funcdecl->fbody = new CompoundStatement(Loc(), s, funcdecl->fbody);
789 }
790 }
791 //printf("callSuper = x%x\n", sc2->callSuper);
792 }
793
794 /* https://issues.dlang.org/show_bug.cgi?id=17502
795 * Wait until after the return type has been inferred before
796 * generating the contracts for this function, and merging contracts
797 * from overrides.
798 *
799 * https://issues.dlang.org/show_bug.cgi?id=17893
800 * However should take care to generate this before inferered
801 * function attributes are applied, such as 'nothrow'.
802 *
803 * This was originally at the end of the first semantic pass, but
804 * required a fix-up to be done here for the '__result' variable
805 * type of __ensure() inside auto functions, but this didn't work
806 * if the out parameter was implicit.
807 */
808 funcdecl->buildEnsureRequire();
809
810 int blockexit = BEnone;
811 if (!funcdecl->fbody->isErrorStatement())
812 {
813 // Check for errors related to 'nothrow'.
814 unsigned int nothrowErrors = global.errors;
815 blockexit = blockExit(funcdecl->fbody, funcdecl, f->isnothrow);
816 if (f->isnothrow && (global.errors != nothrowErrors))
817 error(funcdecl->loc, "nothrow %s `%s` may throw", funcdecl->kind(), funcdecl->toPrettyChars());
818 if (funcdecl->flags & FUNCFLAGnothrowInprocess)
819 {
820 if (funcdecl->type == f) f = (TypeFunction *)f->copy();
821 f->isnothrow = !(blockexit & BEthrow);
822 }
823 }
824
825 if (funcdecl->fbody->isErrorStatement())
826 ;
827 else if (ad2 && funcdecl->isCtorDeclaration())
828 {
829 /* Append:
830 * return this;
831 * to function body
832 */
833 if (blockexit & BEfallthru)
834 {
835 Statement *s = new ReturnStatement(funcdecl->loc, NULL);
836 s = statementSemantic(s, sc2);
837 funcdecl->fbody = new CompoundStatement(funcdecl->loc, funcdecl->fbody, s);
838 funcdecl->hasReturnExp |= (funcdecl->hasReturnExp & 1 ? 16 : 1);
839 }
840 }
841 else if (funcdecl->fes)
842 {
843 // For foreach(){} body, append a return 0;
844 if (blockexit & BEfallthru)
845 {
846 Expression *e = new IntegerExp(0);
847 Statement *s = new ReturnStatement(Loc(), e);
848 funcdecl->fbody = new CompoundStatement(Loc(), funcdecl->fbody, s);
849 funcdecl->hasReturnExp |= (funcdecl->hasReturnExp & 1 ? 16 : 1);
850 }
851 assert(!funcdecl->returnLabel);
852 }
853 else if (f->next->ty == Tnoreturn)
854 {
855 }
856 else
857 {
858 const bool inlineAsm = (funcdecl->hasReturnExp & 8) != 0;
859 if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm)
860 {
861 if (!funcdecl->hasReturnExp)
862 funcdecl->error("has no `return` statement, but is expected to return a value of type `%s`", f->next->toChars());
863 else
864 funcdecl->error("no `return exp;` or `assert(0);` at end of function");
865 }
866 }
867
868 if (funcdecl->returns)
869 {
870 bool implicit0 = addReturn0(funcdecl);
871 Type *tret = implicit0 ? Type::tint32 : f->next;
872 assert(tret->ty != Tvoid);
873 if (funcdecl->vresult || funcdecl->returnLabel)
874 funcdecl->buildResultVar(scout ? scout : sc2, tret);
875
876 /* Cannot move this loop into NrvoWalker, because
877 * returns[i] may be in the nested delegate for foreach-body.
878 */
879 for (size_t i = 0; i < funcdecl->returns->length; i++)
880 {
881 ReturnStatement *rs = (*funcdecl->returns)[i];
882 Expression *exp = rs->exp;
883 if (exp->op == TOKerror)
884 continue;
885 if (tret->ty == Terror)
886 {
887 // Bugzilla 13702
888 exp = checkGC(sc2, exp);
889 continue;
890 }
891
892 if (!exp->implicitConvTo(tret) &&
893 funcdecl->parametersIntersect(exp->type))
894 {
895 if (exp->type->immutableOf()->implicitConvTo(tret))
896 exp = exp->castTo(sc2, exp->type->immutableOf());
897 else if (exp->type->wildOf()->implicitConvTo(tret))
898 exp = exp->castTo(sc2, exp->type->wildOf());
899 }
900 exp = exp->implicitCastTo(sc2, tret);
901
902 if (f->isref)
903 {
904 // Function returns a reference
905 exp = exp->toLvalue(sc2, exp);
906 checkReturnEscapeRef(sc2, exp, false);
907 }
908 else
909 {
910 exp = exp->optimize(WANTvalue);
911
912 /* Bugzilla 10789:
913 * If NRVO is not possible, all returned lvalues should call their postblits.
914 */
915 if (!funcdecl->nrvo_can)
916 exp = doCopyOrMove(sc2, exp);
917
918 if (tret->hasPointers())
919 checkReturnEscape(sc2, exp, false);
920 }
921
922 exp = checkGC(sc2, exp);
923
924 if (funcdecl->vresult)
925 {
926 // Create: return vresult = exp;
927 exp = new BlitExp(rs->loc, funcdecl->vresult, exp);
928 exp->type = funcdecl->vresult->type;
929
930 if (rs->caseDim)
931 exp = Expression::combine(exp, new IntegerExp(rs->caseDim));
932 }
933 else if (funcdecl->tintro && !tret->equals(funcdecl->tintro->nextOf()))
934 {
935 exp = exp->implicitCastTo(sc2, funcdecl->tintro->nextOf());
936 }
937 rs->exp = exp;
938 }
939 }
940 if (funcdecl->nrvo_var || funcdecl->returnLabel)
941 {
942 NrvoWalker nw;
943 nw.fd = funcdecl;
944 nw.sc = sc2;
945 nw.visitStmt(funcdecl->fbody);
946 }
947
948 sc2 = sc2->pop();
949 }
950
951 funcdecl->frequire = funcdecl->mergeFrequire(funcdecl->frequire);
952 funcdecl->fensure = funcdecl->mergeFensure(funcdecl->fensure, Id::result);
953
954 Statement *freq = funcdecl->frequire;
955 Statement *fens = funcdecl->fensure;
956
957 /* Do the semantic analysis on the [in] preconditions and
958 * [out] postconditions.
959 */
960 if (freq)
961 {
962 /* frequire is composed of the [in] contracts
963 */
964 ScopeDsymbol *sym = new ScopeDsymbol();
965 sym->parent = sc2->scopesym;
966 sym->loc = funcdecl->loc;
967 sym->endlinnum = funcdecl->endloc.linnum;
968 sc2 = sc2->push(sym);
969 sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire;
970
971 // BUG: need to error if accessing out parameters
972 // BUG: need to disallow returns and throws
973 // BUG: verify that all in and ref parameters are read
974 freq = statementSemantic(freq, sc2);
975 blockExit(freq, funcdecl, false);
976
977 sc2 = sc2->pop();
978
979 if (global.params.useIn == CHECKENABLEoff)
980 freq = NULL;
981 }
982
983 if (fens)
984 {
985 /* fensure is composed of the [out] contracts
986 */
987 if (f->next->ty == Tvoid && funcdecl->fensures)
988 {
989 for (size_t i = 0; i < funcdecl->fensures->length; i++)
990 {
991 Ensure e = (*funcdecl->fensures)[i];
992 if (e.id)
993 {
994 funcdecl->error(e.ensure->loc, "`void` functions have no result");
995 //fens = NULL;
996 }
997 }
998 }
999
1000 sc2 = scout; //push
1001 sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure;
1002
1003 // BUG: need to disallow returns and throws
1004 if (funcdecl->fensure && f->next->ty != Tvoid)
1005 funcdecl->buildResultVar(scout, f->next);
1006
1007 fens = statementSemantic(fens, sc2);
1008 blockExit(fens, funcdecl, false);
1009
1010 sc2 = sc2->pop();
1011
1012 if (global.params.useOut == CHECKENABLEoff)
1013 fens = NULL;
1014 }
1015
1016 if (funcdecl->fbody && funcdecl->fbody->isErrorStatement())
1017 ;
1018 else
1019 {
1020 Statements *a = new Statements();
1021
1022 // Merge in initialization of 'out' parameters
1023 if (funcdecl->parameters)
1024 {
1025 for (size_t i = 0; i < funcdecl->parameters->length; i++)
1026 {
1027 VarDeclaration *v = (*funcdecl->parameters)[i];
1028 if (v->storage_class & STCout)
1029 {
1030 assert(v->_init);
1031 ExpInitializer *ie = v->_init->isExpInitializer();
1032 assert(ie);
1033 if (ie->exp->op == TOKconstruct)
1034 ie->exp->op = TOKassign; // construction occured in parameter processing
1035 a->push(new ExpStatement(Loc(), ie->exp));
1036 }
1037 }
1038 }
1039
1040 if (funcdecl->v_argptr)
1041 {
1042 // Handled in FuncDeclaration::toObjFile
1043 funcdecl->v_argptr->_init = new VoidInitializer(funcdecl->loc);
1044 }
1045
1046 if (_arguments)
1047 {
1048 /* Advance to elements[] member of TypeInfo_Tuple with:
1049 * _arguments = v_arguments.elements;
1050 */
1051 Expression *e = new VarExp(Loc(), funcdecl->v_arguments);
1052 e = new DotIdExp(Loc(), e, Id::elements);
1053 e = new ConstructExp(Loc(), _arguments, e);
1054 e = expressionSemantic(e, sc2);
1055
1056 _arguments->_init = new ExpInitializer(Loc(), e);
1057 DeclarationExp *de = new DeclarationExp(Loc(), _arguments);
1058 a->push(new ExpStatement(Loc(), de));
1059 }
1060
1061 // Merge contracts together with body into one compound statement
1062
1063 if (freq || fpreinv)
1064 {
1065 if (!freq)
1066 freq = fpreinv;
1067 else if (fpreinv)
1068 freq = new CompoundStatement(Loc(), freq, fpreinv);
1069
1070 a->push(freq);
1071 }
1072
1073 if (funcdecl->fbody)
1074 a->push(funcdecl->fbody);
1075
1076 if (fens || fpostinv)
1077 {
1078 if (!fens)
1079 fens = fpostinv;
1080 else if (fpostinv)
1081 fens = new CompoundStatement(Loc(), fpostinv, fens);
1082
1083 LabelStatement *ls = new LabelStatement(Loc(), Id::returnLabel, fens);
1084 funcdecl->returnLabel->statement = ls;
1085 a->push(funcdecl->returnLabel->statement);
1086
1087 if (f->next->ty != Tvoid && funcdecl->vresult)
1088 {
1089 // Create: return vresult;
1090 Expression *e = new VarExp(Loc(), funcdecl->vresult);
1091 if (funcdecl->tintro)
1092 {
1093 e = e->implicitCastTo(sc, funcdecl->tintro->nextOf());
1094 e = expressionSemantic(e, sc);
1095 }
1096 ReturnStatement *s = new ReturnStatement(Loc(), e);
1097 a->push(s);
1098 }
1099 }
1100 if (addReturn0(funcdecl))
1101 {
1102 // Add a return 0; statement
1103 Statement *s = new ReturnStatement(Loc(), new IntegerExp(0));
1104 a->push(s);
1105 }
1106
1107 Statement *sbody = new CompoundStatement(Loc(), a);
1108 /* Append destructor calls for parameters as finally blocks.
1109 */
1110 if (funcdecl->parameters)
1111 {
1112 for (size_t i = 0; i < funcdecl->parameters->length; i++)
1113 {
1114 VarDeclaration *v = (*funcdecl->parameters)[i];
1115
1116 if (v->storage_class & (STCref | STCout | STClazy))
1117 continue;
1118
1119 if (v->needsScopeDtor())
1120 {
1121 // same with ExpStatement.scopeCode()
1122 Statement *s = new DtorExpStatement(Loc(), v->edtor, v);
1123 v->storage_class |= STCnodtor;
1124
1125 s = statementSemantic(s, sc2);
1126
1127 bool isnothrow = f->isnothrow & !(funcdecl->flags & FUNCFLAGnothrowInprocess);
1128 int blockexit = blockExit(s, funcdecl, isnothrow);
1129 if (f->isnothrow && isnothrow && blockexit & BEthrow)
1130 error(funcdecl->loc, "nothrow %s `%s` may throw", funcdecl->kind(), funcdecl->toPrettyChars());
1131 if (funcdecl->flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
1132 f->isnothrow = false;
1133 if (blockExit(sbody, funcdecl, f->isnothrow) == BEfallthru)
1134 sbody = new CompoundStatement(Loc(), sbody, s);
1135 else
1136 sbody = new TryFinallyStatement(Loc(), sbody, s);
1137 }
1138 }
1139 }
1140 // from this point on all possible 'throwers' are checked
1141 funcdecl->flags &= ~FUNCFLAGnothrowInprocess;
1142
1143 if (funcdecl->isSynchronized())
1144 {
1145 /* Wrap the entire function body in a synchronized statement
1146 */
1147 ClassDeclaration *cd = funcdecl->isThis() ? funcdecl->isThis()->isClassDeclaration() : funcdecl->parent->isClassDeclaration();
1148
1149 if (cd)
1150 {
1151 if (target.libraryObjectMonitors(funcdecl, sbody))
1152 {
1153 Expression *vsync;
1154 if (funcdecl->isStatic())
1155 {
1156 // The monitor is in the ClassInfo
1157 vsync = new DotIdExp(funcdecl->loc, resolve(funcdecl->loc, sc2, cd, false), Id::classinfo);
1158 }
1159 else
1160 {
1161 // 'this' is the monitor
1162 vsync = new VarExp(funcdecl->loc, funcdecl->vthis);
1163 }
1164 sbody = new PeelStatement(sbody); // don't redo semantic()
1165 sbody = new SynchronizedStatement(funcdecl->loc, vsync, sbody);
1166 sbody = statementSemantic(sbody, sc2);
1167 }
1168 }
1169 else
1170 {
1171 funcdecl->error("synchronized function %s must be a member of a class", funcdecl->toChars());
1172 }
1173 }
1174
1175 // If declaration has no body, don't set sbody to prevent incorrect codegen.
1176 if (funcdecl->fbody || allowsContractWithoutBody(funcdecl))
1177 funcdecl->fbody = sbody;
1178 }
1179
1180 // Fix up forward-referenced gotos
1181 if (funcdecl->gotos)
1182 {
1183 for (size_t i = 0; i < funcdecl->gotos->length; ++i)
1184 {
1185 (*funcdecl->gotos)[i]->checkLabel();
1186 }
1187 }
1188
1189 if (funcdecl->naked && (funcdecl->fensures || funcdecl->frequires))
1190 funcdecl->error("naked assembly functions with contracts are not supported");
1191
1192 sc2->callSuper = 0;
1193 sc2->pop();
1194 }
1195
1196 if (funcdecl->checkClosure())
1197 {
1198 // We should be setting errors here instead of relying on the global error count.
1199 //errors = true;
1200 }
1201
1202 /* If function survived being marked as impure, then it is pure
1203 */
1204 if (funcdecl->flags & FUNCFLAGpurityInprocess)
1205 {
1206 funcdecl->flags &= ~FUNCFLAGpurityInprocess;
1207 if (funcdecl->type == f)
1208 f = (TypeFunction *)f->copy();
1209 f->purity = PUREfwdref;
1210 }
1211
1212 if (funcdecl->flags & FUNCFLAGsafetyInprocess)
1213 {
1214 funcdecl->flags &= ~FUNCFLAGsafetyInprocess;
1215 if (funcdecl->type == f)
1216 f = (TypeFunction *)f->copy();
1217 f->trust = TRUSTsafe;
1218 }
1219
1220 if (funcdecl->flags & FUNCFLAGnogcInprocess)
1221 {
1222 funcdecl->flags &= ~FUNCFLAGnogcInprocess;
1223 if (funcdecl->type == f)
1224 f = (TypeFunction *)f->copy();
1225 f->isnogc = true;
1226 }
1227
1228 if (funcdecl->flags & FUNCFLAGreturnInprocess)
1229 {
1230 funcdecl->flags &= ~FUNCFLAGreturnInprocess;
1231 if (funcdecl->storage_class & STCreturn)
1232 {
1233 if (funcdecl->type == f)
1234 f = (TypeFunction *)f->copy();
1235 f->isreturn = true;
1236 }
1237 }
1238
1239 funcdecl->flags &= ~FUNCFLAGinferScope;
1240
1241 // Infer STCscope
1242 if (funcdecl->parameters)
1243 {
1244 size_t nfparams = f->parameterList.length();
1245 assert(nfparams == funcdecl->parameters->length);
1246 for (size_t u = 0; u < funcdecl->parameters->length; u++)
1247 {
1248 VarDeclaration *v = (*funcdecl->parameters)[u];
1249 if (v->storage_class & STCmaybescope)
1250 {
1251 //printf("Inferring scope for %s\n", v->toChars());
1252 Parameter *p = f->parameterList[u];
1253 v->storage_class &= ~STCmaybescope;
1254 v->storage_class |= STCscope | STCscopeinferred;
1255 p->storageClass |= STCscope | STCscopeinferred;
1256 assert(!(p->storageClass & STCmaybescope));
1257 }
1258 }
1259 }
1260
1261 if (funcdecl->vthis && funcdecl->vthis->storage_class & STCmaybescope)
1262 {
1263 funcdecl->vthis->storage_class &= ~STCmaybescope;
1264 funcdecl->vthis->storage_class |= STCscope | STCscopeinferred;
1265 f->isscope = true;
1266 f->isscopeinferred = true;
1267 }
1268
1269 // reset deco to apply inference result to mangled name
1270 if (f != funcdecl->type)
1271 f->deco = NULL;
1272
1273 // Do semantic type AFTER pure/nothrow inference.
1274 if (!f->deco && funcdecl->ident != Id::xopEquals && funcdecl->ident != Id::xopCmp)
1275 {
1276 sc = sc->push();
1277 if (funcdecl->isCtorDeclaration()) // Bugzilla #15665
1278 sc->flags |= SCOPEctor;
1279 sc->stc = 0;
1280 sc->linkage = funcdecl->linkage; // Bugzilla 8496
1281 funcdecl->type = typeSemantic(f, funcdecl->loc, sc);
1282 sc = sc->pop();
1283 }
1284
1285 /* If this function had instantiated with gagging, error reproduction will be
1286 * done by TemplateInstance::semantic.
1287 * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
1288 */
1289 funcdecl->semanticRun = PASSsemantic3done;
1290 funcdecl->semantic3Errors = (global.errors != oldErrors) || (funcdecl->fbody && funcdecl->fbody->isErrorStatement());
1291 if (funcdecl->type->ty == Terror)
1292 funcdecl->errors = true;
1293 //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", funcdecl->parent->toChars(), funcdecl->toChars(), sc, funcdecl->loc.toChars());
1294 //fflush(stdout);
1295 }
1296
visit(Nspace * ns)1297 void visit(Nspace *ns)
1298 {
1299 if (ns->semanticRun >= PASSsemantic3)
1300 return;
1301 ns->semanticRun = PASSsemantic3;
1302 if (ns->members)
1303 {
1304 sc = sc->push(ns);
1305 sc->linkage = LINKcpp;
1306 for (size_t i = 0; i < ns->members->length; i++)
1307 {
1308 Dsymbol *s = (*ns->members)[i];
1309 semantic3(s, sc);
1310 }
1311 sc->pop();
1312 }
1313 }
1314
visit(AttribDeclaration * ad)1315 void visit(AttribDeclaration *ad)
1316 {
1317 Dsymbols *d = ad->include(sc);
1318
1319 if (d)
1320 {
1321 Scope *sc2 = ad->newScope(sc);
1322
1323 for (size_t i = 0; i < d->length; i++)
1324 {
1325 Dsymbol *s = (*d)[i];
1326 semantic3(s, sc2);
1327 }
1328
1329 if (sc2 != sc)
1330 sc2->pop();
1331 }
1332 }
1333
visit(AggregateDeclaration * ad)1334 void visit(AggregateDeclaration *ad)
1335 {
1336 //printf("AggregateDeclaration::semantic3(%s) type = %s, errors = %d\n", ad->toChars(), ad->type->toChars(), ad->errors);
1337 if (!ad->members)
1338 return;
1339
1340 StructDeclaration *sd = ad->isStructDeclaration();
1341 if (!sc) // from runDeferredSemantic3 for TypeInfo generation
1342 {
1343 assert(sd);
1344 sd->semanticTypeInfoMembers();
1345 return;
1346 }
1347
1348 Scope *sc2 = ad->newScope(sc);
1349
1350 for (size_t i = 0; i < ad->members->length; i++)
1351 {
1352 Dsymbol *s = (*ad->members)[i];
1353 semantic3(s, sc2);
1354 }
1355
1356 sc2->pop();
1357
1358 // don't do it for unused deprecated types
1359 // or error types
1360 if (!ad->getRTInfo && Type::rtinfo &&
1361 (!ad->isDeprecated() || global.params.useDeprecated != DIAGNOSTICerror) &&
1362 (ad->type && ad->type->ty != Terror))
1363 {
1364 // Evaluate: RTinfo!type
1365 Objects *tiargs = new Objects();
1366 tiargs->push(ad->type);
1367 TemplateInstance *ti = new TemplateInstance(ad->loc, Type::rtinfo, tiargs);
1368
1369 Scope *sc3 = ti->tempdecl->_scope->startCTFE();
1370 sc3->tinst = sc->tinst;
1371 sc3->minst = sc->minst;
1372 if (ad->isDeprecated())
1373 sc3->stc |= STCdeprecated;
1374
1375 dsymbolSemantic(ti, sc3);
1376 semantic2(ti, sc3);
1377 semantic3(ti, sc3);
1378 Expression *e = resolve(Loc(), sc3, ti->toAlias(), false);
1379
1380 sc3->endCTFE();
1381
1382 e = e->ctfeInterpret();
1383 ad->getRTInfo = e;
1384 }
1385
1386 if (sd)
1387 sd->semanticTypeInfoMembers();
1388 ad->semanticRun = PASSsemantic3done;
1389 }
1390 };
1391
1392 /*************************************
1393 * Does semantic analysis on function bodies.
1394 */
semantic3(Dsymbol * dsym,Scope * sc)1395 void semantic3(Dsymbol *dsym, Scope *sc)
1396 {
1397 Semantic3Visitor v(sc);
1398 dsym->accept(&v);
1399 }
1400