comparison dmd/func.c @ 1:c53b6e3fe49a trunk

[svn r5] Initial commit. Most things are very rough.
author lindquist
date Sat, 01 Sep 2007 21:43:27 +0200
parents
children d3ee9efe20e2
comparison
equal deleted inserted replaced
0:a9e71648e74d 1:c53b6e3fe49a
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
10
11 #include <stdio.h>
12 #include <assert.h>
13
14 #include "mars.h"
15 #include "init.h"
16 #include "declaration.h"
17 #include "attrib.h"
18 #include "expression.h"
19 #include "scope.h"
20 #include "mtype.h"
21 #include "aggregate.h"
22 #include "identifier.h"
23 #include "id.h"
24 #include "module.h"
25 #include "statement.h"
26 #include "template.h"
27 #include "hdrgen.h"
28
29 #ifdef IN_GCC
30 #include "d-dmd-gcc.h"
31 #endif
32
33 /********************************* FuncDeclaration ****************************/
34
35 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
36 : Declaration(id)
37 {
38 this->storage_class = storage_class;
39 this->type = type;
40 this->loc = loc;
41 this->endloc = endloc;
42 fthrows = NULL;
43 frequire = NULL;
44 outId = NULL;
45 vresult = NULL;
46 returnLabel = NULL;
47 fensure = NULL;
48 fbody = NULL;
49 localsymtab = NULL;
50 vthis = NULL;
51 v_arguments = NULL;
52 #if IN_GCC
53 v_argptr = NULL;
54 #endif
55 parameters = NULL;
56 labtab = NULL;
57 overnext = NULL;
58 vtblIndex = -1;
59 hasReturnExp = 0;
60 naked = 0;
61 inlineStatus = ILSuninitialized;
62 inlineNest = 0;
63 inlineAsm = 0;
64 cantInterpret = 0;
65 semanticRun = 0;
66 nestedFrameRef = 0;
67 fes = NULL;
68 introducing = 0;
69 tintro = NULL;
70 inferRetType = (type && type->nextOf() == NULL);
71 scope = NULL;
72 hasReturnExp = 0;
73 nrvo_can = 1;
74 nrvo_var = NULL;
75 shidden = NULL;
76 }
77
78 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
79 {
80 FuncDeclaration *f;
81
82 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
83 if (s)
84 f = (FuncDeclaration *)s;
85 else
86 f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
87 f->outId = outId;
88 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
89 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
90 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
91 assert(!fthrows); // deprecated
92 return f;
93 }
94
95
96 // Do the semantic analysis on the external interface to the function.
97
98 void FuncDeclaration::semantic(Scope *sc)
99 { TypeFunction *f;
100 StructDeclaration *sd;
101 ClassDeclaration *cd;
102 InterfaceDeclaration *id;
103
104 #if 0
105 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
106 if (isFuncLiteralDeclaration())
107 printf("\tFuncLiteralDeclaration()\n");
108 printf("sc->parent = %s\n", sc->parent->toChars());
109 printf("type: %s\n", type->toChars());
110 #endif
111
112 if (type->nextOf())
113 type = type->semantic(loc, sc);
114 //type->print();
115 if (type->ty != Tfunction)
116 {
117 error("%s must be a function", toChars());
118 return;
119 }
120 f = (TypeFunction *)(type);
121 size_t nparams = Argument::dim(f->parameters);
122
123 linkage = sc->linkage;
124 // if (!parent)
125 {
126 //parent = sc->scopesym;
127 parent = sc->parent;
128 }
129 protection = sc->protection;
130 storage_class |= sc->stc;
131 //printf("function storage_class = x%x\n", storage_class);
132 Dsymbol *parent = toParent();
133
134 if (isConst() || isAuto() || isScope())
135 error("functions cannot be const or auto");
136
137 if (isAbstract() && !isVirtual())
138 error("non-virtual functions cannot be abstract");
139 #if 0
140 if (isAbstract() && fbody)
141 error("abstract functions cannot have bodies");
142 #endif
143
144 #if 0
145 if (isStaticConstructor() || isStaticDestructor())
146 {
147 if (!isStatic() || type->nextOf()->ty != Tvoid)
148 error("static constructors / destructors must be static void");
149 if (f->arguments && f->arguments->dim)
150 error("static constructors / destructors must have empty parameter list");
151 // BUG: check for invalid storage classes
152 }
153 #endif
154
155 #ifdef IN_GCC
156 AggregateDeclaration *ad;
157
158 ad = parent->isAggregateDeclaration();
159 if (ad)
160 ad->methods.push(this);
161 #endif
162 sd = parent->isStructDeclaration();
163 if (sd)
164 {
165 // Verify no constructors, destructors, etc.
166 if (isCtorDeclaration() ||
167 isDtorDeclaration()
168 //|| isInvariantDeclaration()
169 //|| isUnitTestDeclaration()
170 )
171 {
172 error("special member functions not allowed for %ss", sd->kind());
173 }
174
175 #if 0
176 if (!sd->inv)
177 sd->inv = isInvariantDeclaration();
178
179 if (!sd->aggNew)
180 sd->aggNew = isNewDeclaration();
181
182 if (isDelete())
183 {
184 if (sd->aggDelete)
185 error("multiple delete's for struct %s", sd->toChars());
186 sd->aggDelete = (DeleteDeclaration *)(this);
187 }
188 #endif
189 }
190
191 id = parent->isInterfaceDeclaration();
192 if (id)
193 {
194 storage_class |= STCabstract;
195
196 if (isCtorDeclaration() ||
197 isDtorDeclaration() ||
198 isInvariantDeclaration() ||
199 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
200 error("special function not allowed in interface %s", id->toChars());
201 if (fbody)
202 error("function body is not abstract in interface %s", id->toChars());
203 }
204
205 cd = parent->isClassDeclaration();
206 if (cd)
207 { int vi;
208 CtorDeclaration *ctor;
209 DtorDeclaration *dtor;
210 InvariantDeclaration *inv;
211
212 if (isCtorDeclaration())
213 {
214 // ctor = (CtorDeclaration *)this;
215 // if (!cd->ctor)
216 // cd->ctor = ctor;
217 return;
218 }
219
220 #if 0
221 dtor = isDtorDeclaration();
222 if (dtor)
223 {
224 if (cd->dtor)
225 error("multiple destructors for class %s", cd->toChars());
226 cd->dtor = dtor;
227 }
228
229 inv = isInvariantDeclaration();
230 if (inv)
231 {
232 cd->inv = inv;
233 }
234
235 if (isNewDeclaration())
236 {
237 if (!cd->aggNew)
238 cd->aggNew = (NewDeclaration *)(this);
239 }
240
241 if (isDelete())
242 {
243 if (cd->aggDelete)
244 error("multiple delete's for class %s", cd->toChars());
245 cd->aggDelete = (DeleteDeclaration *)(this);
246 }
247 #endif
248
249 if (storage_class & STCabstract)
250 cd->isabstract = 1;
251
252 // if static function, do not put in vtbl[]
253 if (!isVirtual())
254 {
255 //printf("\tnot virtual\n");
256 return;
257 }
258
259 // Find index of existing function in vtbl[] to override
260 if (cd->baseClass)
261 {
262 for (vi = 0; vi < cd->baseClass->vtbl.dim; vi++)
263 {
264 FuncDeclaration *fdv = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration();
265
266 // BUG: should give error if argument types match,
267 // but return type does not?
268
269 //printf("\tvtbl[%d] = '%s'\n", vi, fdv ? fdv->ident->toChars() : "");
270 if (fdv && fdv->ident == ident)
271 {
272 int cov = type->covariant(fdv->type);
273 //printf("\tbaseclass cov = %d\n", cov);
274 if (cov == 2)
275 {
276 //type->print();
277 //fdv->type->print();
278 //printf("%s %s\n", type->deco, fdv->type->deco);
279 error("of type %s overrides but is not covariant with %s of type %s",
280 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
281 }
282 if (cov == 1)
283 {
284 if (fdv->isFinal())
285 error("cannot override final function %s", fdv->toPrettyChars());
286 if (fdv->toParent() == parent)
287 {
288 // If both are mixins, then error.
289 // If either is not, the one that is not overrides
290 // the other.
291 if (fdv->parent->isClassDeclaration())
292 goto L1;
293 if (!this->parent->isClassDeclaration()
294 #if !BREAKABI
295 && !isDtorDeclaration()
296 #endif
297 )
298 error("multiple overrides of same function");
299 }
300 cd->vtbl.data[vi] = (void *)this;
301 vtblIndex = vi;
302
303 /* This works by whenever this function is called,
304 * it actually returns tintro, which gets dynamically
305 * cast to type. But we know that tintro is a base
306 * of type, so we could optimize it by not doing a
307 * dynamic cast, but just subtracting the isBaseOf()
308 * offset if the value is != null.
309 */
310
311 if (fdv->tintro)
312 tintro = fdv->tintro;
313 else if (!type->equals(fdv->type))
314 {
315 /* Only need to have a tintro if the vptr
316 * offsets differ
317 */
318 int offset;
319 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
320 {
321 tintro = fdv->type;
322 }
323 }
324 goto L1;
325 }
326 if (cov == 3)
327 {
328 cd->sizeok = 2; // can't finish due to forward reference
329 return;
330 }
331 }
332 }
333 }
334
335 // This is an 'introducing' function.
336
337 // Verify this doesn't override previous final function
338 if (cd->baseClass)
339 { Dsymbol *s = cd->baseClass->search(loc, ident, 0);
340 if (s)
341 {
342 FuncDeclaration *f = s->isFuncDeclaration();
343 f = f->overloadExactMatch(type);
344 if (f && f->isFinal() && f->prot() != PROTprivate)
345 error("cannot override final function %s", f->toPrettyChars());
346 }
347 }
348
349 if (isFinal())
350 {
351 cd->vtblFinal.push(this);
352 }
353 else
354 {
355 // Append to end of vtbl[]
356 //printf("\tintroducing function\n");
357 introducing = 1;
358 vi = cd->vtbl.dim;
359 cd->vtbl.push(this);
360 vtblIndex = vi;
361 }
362
363 L1: ;
364
365 /* Go through all the interface bases.
366 * If this function is covariant with any members of those interface
367 * functions, set the tintro.
368 */
369 for (int i = 0; i < cd->interfaces_dim; i++)
370 {
371 BaseClass *b = cd->interfaces[i];
372 for (vi = 0; vi < b->base->vtbl.dim; vi++)
373 {
374 Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
375 //printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
376 FuncDeclaration *fdv = s->isFuncDeclaration();
377 if (fdv && fdv->ident == ident)
378 {
379 int cov = type->covariant(fdv->type);
380 //printf("\tcov = %d\n", cov);
381 if (cov == 2)
382 {
383 //type->print();
384 //fdv->type->print();
385 //printf("%s %s\n", type->deco, fdv->type->deco);
386 error("of type %s overrides but is not covariant with %s of type %s",
387 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
388 }
389 if (cov == 1)
390 { Type *ti = NULL;
391
392 if (fdv->tintro)
393 ti = fdv->tintro;
394 else if (!type->equals(fdv->type))
395 {
396 /* Only need to have a tintro if the vptr
397 * offsets differ
398 */
399 int offset;
400 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
401 {
402 ti = fdv->type;
403 #if 0
404 if (offset)
405 ti = fdv->type;
406 else if (type->next->ty == Tclass)
407 { ClassDeclaration *cdn = ((TypeClass *)type->next)->sym;
408 if (cdn && cdn->sizeok != 1)
409 ti = fdv->type;
410 }
411 #endif
412 }
413 }
414 if (ti)
415 {
416 if (tintro && !tintro->equals(ti))
417 {
418 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
419 }
420 tintro = ti;
421 }
422 goto L2;
423 }
424 if (cov == 3)
425 {
426 cd->sizeok = 2; // can't finish due to forward reference
427 return;
428 }
429 }
430 }
431 }
432
433 if (introducing && isOverride())
434 {
435 error("function %s does not override any", toChars());
436 }
437
438 L2: ;
439 }
440 else if (isOverride() && !parent->isTemplateInstance())
441 error("override only applies to class member functions");
442
443 /* Do not allow template instances to add virtual functions
444 * to a class.
445 */
446 if (isVirtual())
447 {
448 TemplateInstance *ti = parent->isTemplateInstance();
449 if (ti)
450 {
451 // Take care of nested templates
452 while (1)
453 {
454 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
455 if (!ti2)
456 break;
457 ti = ti2;
458 }
459
460 // If it's a member template
461 ClassDeclaration *cd = ti->tempdecl->isClassMember();
462 if (cd)
463 {
464 error("cannot use template to add virtual function to class '%s'", cd->toChars());
465 }
466 }
467 }
468
469 if (isMain())
470 {
471 // Check parameters to see if they are either () or (char[][] args)
472 switch (nparams)
473 {
474 case 0:
475 break;
476
477 case 1:
478 {
479 Argument *arg0 = Argument::getNth(f->parameters, 0);
480 if (arg0->type->ty != Tarray ||
481 arg0->type->next->ty != Tarray ||
482 arg0->type->next->next->ty != Tchar ||
483 arg0->storageClass & (STCout | STCref | STClazy))
484 goto Lmainerr;
485 break;
486 }
487
488 default:
489 goto Lmainerr;
490 }
491
492 if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
493 error("must return int or void, not %s", f->nextOf()->toChars());
494 if (f->varargs)
495 {
496 Lmainerr:
497 error("parameters must be main() or main(char[][] args)");
498 }
499 }
500
501 if (ident == Id::assign && (sd || cd))
502 { // Disallow identity assignment operator.
503
504 // opAssign(...)
505 if (nparams == 0)
506 { if (f->varargs == 1)
507 goto Lassignerr;
508 }
509 else
510 {
511 Argument *arg0 = Argument::getNth(f->parameters, 0);
512 Type *t0 = arg0->type->toBasetype();
513 Type *tb = sd ? sd->type : cd->type;
514 if (arg0->type->implicitConvTo(tb) ||
515 (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
516 )
517 {
518 if (nparams == 1)
519 goto Lassignerr;
520 Argument *arg1 = Argument::getNth(f->parameters, 1);
521 if (arg1->defaultArg)
522 goto Lassignerr;
523 }
524 }
525 }
526
527 /* Save scope for possible later use (if we need the
528 * function internals)
529 */
530 scope = new Scope(*sc);
531 scope->setNoFree();
532 return;
533
534 Lassignerr:
535 error("identity assignment operator overload is illegal");
536 }
537
538 void FuncDeclaration::semantic2(Scope *sc)
539 {
540 }
541
542 // Do the semantic analysis on the internals of the function.
543
544 void FuncDeclaration::semantic3(Scope *sc)
545 { TypeFunction *f;
546 AggregateDeclaration *ad;
547 VarDeclaration *argptr = NULL;
548 VarDeclaration *_arguments = NULL;
549
550 if (!parent)
551 {
552 printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
553 assert(0);
554 }
555 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p)\n", parent->toChars(), toChars(), sc);
556 //fflush(stdout);
557 //{ static int x; if (++x == 2) *(char*)0=0; }
558 //printf("\tlinkage = %d\n", sc->linkage);
559
560 //printf(" sc->incontract = %d\n", sc->incontract);
561 if (semanticRun)
562 return;
563 semanticRun = 1;
564
565 if (!type || type->ty != Tfunction)
566 return;
567 f = (TypeFunction *)(type);
568 size_t nparams = Argument::dim(f->parameters);
569
570 // Check the 'throws' clause
571 if (fthrows)
572 { int i;
573
574 for (i = 0; i < fthrows->dim; i++)
575 {
576 Type *t = (Type *)fthrows->data[i];
577
578 t = t->semantic(loc, sc);
579 if (!t->isClassHandle())
580 error("can only throw classes, not %s", t->toChars());
581 }
582 }
583
584 if (fbody || frequire)
585 {
586 // Establish function scope
587 ScopeDsymbol *ss;
588 Scope *sc2;
589
590 localsymtab = new DsymbolTable();
591
592 ss = new ScopeDsymbol();
593 ss->parent = sc->scopesym;
594 sc2 = sc->push(ss);
595 sc2->func = this;
596 sc2->parent = this;
597 sc2->callSuper = 0;
598 sc2->sbreak = NULL;
599 sc2->scontinue = NULL;
600 sc2->sw = NULL;
601 sc2->fes = fes;
602 sc2->linkage = LINKd;
603 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated);
604 sc2->protection = PROTpublic;
605 sc2->explicitProtection = 0;
606 sc2->structalign = 8;
607 sc2->incontract = 0;
608 sc2->tf = NULL;
609 sc2->noctor = 0;
610
611 // Declare 'this'
612 ad = isThis();
613 if (ad)
614 { VarDeclaration *v;
615
616 if (isFuncLiteralDeclaration() && isNested())
617 {
618 error("literals cannot be class members");
619 return;
620 }
621 else
622 {
623 assert(!isNested()); // can't be both member and nested
624 assert(ad->handle);
625 v = new ThisDeclaration(ad->handle);
626 v->storage_class |= STCparameter | STCin;
627 v->semantic(sc2);
628 if (!sc2->insert(v))
629 assert(0);
630 v->parent = this;
631 vthis = v;
632 }
633 }
634 else if (isNested())
635 {
636 VarDeclaration *v;
637
638 v = new ThisDeclaration(Type::tvoid->pointerTo());
639 v->storage_class |= STCparameter | STCin;
640 v->semantic(sc2);
641 if (!sc2->insert(v))
642 assert(0);
643 v->parent = this;
644 vthis = v;
645 }
646
647 // Declare hidden variable _arguments[] and _argptr
648 if (f->varargs == 1)
649 { Type *t;
650
651 if (f->linkage == LINKd)
652 { // Declare _arguments[]
653 #if BREAKABI
654 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
655 v_arguments->storage_class = STCparameter | STCin;
656 v_arguments->semantic(sc2);
657 sc2->insert(v_arguments);
658 v_arguments->parent = this;
659
660 t = Type::typeinfo->type->arrayOf();
661 _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
662 _arguments->semantic(sc2);
663 sc2->insert(_arguments);
664 _arguments->parent = this;
665 #else
666 t = Type::typeinfo->type->arrayOf();
667 v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
668 v_arguments->storage_class = STCparameter | STCin;
669 v_arguments->semantic(sc2);
670 sc2->insert(v_arguments);
671 v_arguments->parent = this;
672 #endif
673 }
674 if (f->linkage == LINKd || (parameters && parameters->dim))
675 { // Declare _argptr
676 #if IN_GCC
677 t = d_gcc_builtin_va_list_d_type;
678 #else
679 t = Type::tvoid->pointerTo();
680 #endif
681 argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
682 argptr->semantic(sc2);
683 sc2->insert(argptr);
684 argptr->parent = this;
685 }
686 }
687
688 // Propagate storage class from tuple arguments to their sub-arguments.
689 if (f->parameters)
690 {
691 for (size_t i = 0; i < f->parameters->dim; i++)
692 { Argument *arg = (Argument *)f->parameters->data[i];
693
694 if (arg->type->ty == Ttuple)
695 { TypeTuple *t = (TypeTuple *)arg->type;
696 size_t dim = Argument::dim(t->arguments);
697 for (size_t j = 0; j < dim; j++)
698 { Argument *narg = Argument::getNth(t->arguments, j);
699 narg->storageClass = arg->storageClass;
700 }
701 }
702 }
703 }
704
705 // Declare all the function parameters as variables
706 if (nparams)
707 { // parameters[] has all the tuples removed, as the back end
708 // doesn't know about tuples
709 parameters = new Dsymbols();
710 parameters->reserve(nparams);
711 for (size_t i = 0; i < nparams; i++)
712 {
713 Argument *arg = Argument::getNth(f->parameters, i);
714 Identifier *id = arg->ident;
715 if (!id)
716 {
717 //error("no identifier for parameter %d of %s", i + 1, toChars());
718 OutBuffer buf;
719 buf.printf("_param_%zu", i);
720 char *name = (char *)buf.extractData();
721 id = new Identifier(name, TOKidentifier);
722 arg->ident = id;
723 }
724 VarDeclaration *v = new VarDeclaration(0, arg->type, id, NULL);
725 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
726 v->storage_class |= STCparameter;
727 if (f->varargs == 2 && i + 1 == nparams)
728 v->storage_class |= STCvariadic;
729 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy);
730 if (v->storage_class & STClazy)
731 v->storage_class |= STCin;
732 v->semantic(sc2);
733 if (!sc2->insert(v))
734 error("parameter %s.%s is already defined", toChars(), v->toChars());
735 else
736 parameters->push(v);
737 localsymtab->insert(v);
738 v->parent = this;
739 // for llvm d
740 arg->vardecl = v;
741 }
742 }
743
744 // Declare the tuple symbols and put them in the symbol table,
745 // but not in parameters[].
746 if (f->parameters)
747 {
748 for (size_t i = 0; i < f->parameters->dim; i++)
749 { Argument *arg = (Argument *)f->parameters->data[i];
750
751 if (!arg->ident)
752 continue; // never used, so ignore
753 if (arg->type->ty == Ttuple)
754 { TypeTuple *t = (TypeTuple *)arg->type;
755 size_t dim = Argument::dim(t->arguments);
756 Objects *exps = new Objects();
757 exps->setDim(dim);
758 for (size_t j = 0; j < dim; j++)
759 { Argument *narg = Argument::getNth(t->arguments, j);
760 assert(narg->ident);
761 VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
762 assert(v);
763 Expression *e = new VarExp(0, v);
764 exps->data[j] = (void *)e;
765 }
766 assert(arg->ident);
767 TupleDeclaration *v = new TupleDeclaration(0, arg->ident, exps);
768 //printf("declaring tuple %s\n", v->toChars());
769 v->isexp = 1;
770 if (!sc2->insert(v))
771 error("parameter %s.%s is already defined", toChars(), v->toChars());
772 localsymtab->insert(v);
773 v->parent = this;
774 }
775 }
776 }
777
778 sc2->incontract++;
779
780 if (frequire)
781 {
782 // BUG: need to error if accessing out parameters
783 // BUG: need to treat parameters as const
784 // BUG: need to disallow returns and throws
785 // BUG: verify that all in and ref parameters are read
786 frequire = frequire->semantic(sc2);
787 labtab = NULL; // so body can't refer to labels
788 }
789
790 if (fensure || addPostInvariant())
791 {
792 ScopeDsymbol *sym;
793
794 sym = new ScopeDsymbol();
795 sym->parent = sc2->scopesym;
796 sc2 = sc2->push(sym);
797
798 assert(type->nextOf());
799 if (type->nextOf()->ty == Tvoid)
800 {
801 if (outId)
802 error("void functions have no result");
803 }
804 else
805 {
806 if (!outId)
807 outId = Id::result; // provide a default
808 }
809
810 if (outId)
811 { // Declare result variable
812 VarDeclaration *v;
813 Loc loc = this->loc;
814
815 if (fensure)
816 loc = fensure->loc;
817
818 v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
819 v->noauto = 1;
820 sc2->incontract--;
821 v->semantic(sc2);
822 sc2->incontract++;
823 if (!sc2->insert(v))
824 error("out result %s is already defined", v->toChars());
825 v->parent = this;
826 vresult = v;
827
828 // vresult gets initialized with the function return value
829 // in ReturnStatement::semantic()
830 }
831
832 // BUG: need to treat parameters as const
833 // BUG: need to disallow returns and throws
834 if (fensure)
835 { fensure = fensure->semantic(sc2);
836 labtab = NULL; // so body can't refer to labels
837 }
838
839 if (!global.params.useOut)
840 { fensure = NULL; // discard
841 vresult = NULL;
842 }
843
844 // Postcondition invariant
845 if (addPostInvariant())
846 {
847 Expression *e = NULL;
848 if (isCtorDeclaration())
849 {
850 // Call invariant directly only if it exists
851 InvariantDeclaration *inv = ad->inv;
852 ClassDeclaration *cd = ad->isClassDeclaration();
853
854 while (!inv && cd)
855 {
856 cd = cd->baseClass;
857 if (!cd)
858 break;
859 inv = cd->inv;
860 }
861 if (inv)
862 {
863 e = new DsymbolExp(0, inv);
864 e = new CallExp(0, e);
865 e = e->semantic(sc2);
866 }
867 }
868 else
869 { // Call invariant virtually
870 ThisExp *v = new ThisExp(0);
871 v->type = vthis->type;
872 e = new AssertExp(0, v);
873 }
874 if (e)
875 {
876 ExpStatement *s = new ExpStatement(0, e);
877 if (fensure)
878 fensure = new CompoundStatement(0, s, fensure);
879 else
880 fensure = s;
881 }
882 }
883
884 if (fensure)
885 { returnLabel = new LabelDsymbol(Id::returnLabel);
886 LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
887 ls->isReturnLabel = 1;
888 returnLabel->statement = ls;
889 }
890 sc2 = sc2->pop();
891 }
892
893 sc2->incontract--;
894
895 if (fbody)
896 { ClassDeclaration *cd = isClassMember();
897
898 if (isCtorDeclaration() && cd)
899 {
900 for (int i = 0; i < cd->fields.dim; i++)
901 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
902
903 v->ctorinit = 0;
904 }
905 }
906
907 if (inferRetType || f->retStyle() != RETstack)
908 nrvo_can = 0;
909
910 fbody = fbody->semantic(sc2);
911
912 if (inferRetType)
913 { // If no return type inferred yet, then infer a void
914 if (!type->nextOf())
915 {
916 type->next = Type::tvoid;
917 type = type->semantic(loc, sc);
918 }
919 f = (TypeFunction *)type;
920 }
921
922 int offend = fbody ? fbody->fallOffEnd() : TRUE;
923
924 if (isStaticCtorDeclaration())
925 { /* It's a static constructor. Ensure that all
926 * ctor consts were initialized.
927 */
928
929 ScopeDsymbol *ad = toParent()->isScopeDsymbol();
930 assert(ad);
931 for (int i = 0; i < ad->members->dim; i++)
932 { Dsymbol *s = (Dsymbol *)ad->members->data[i];
933
934 s->checkCtorConstInit();
935 }
936 }
937
938 if (isCtorDeclaration() && cd)
939 {
940 //printf("callSuper = x%x\n", sc2->callSuper);
941
942 // Verify that all the ctorinit fields got initialized
943 if (!(sc2->callSuper & CSXthis_ctor))
944 {
945 for (int i = 0; i < cd->fields.dim; i++)
946 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
947
948 if (v->ctorinit == 0 && v->isCtorinit())
949 error("missing initializer for const field %s", v->toChars());
950 }
951 }
952
953 if (!(sc2->callSuper & CSXany_ctor) &&
954 cd->baseClass && cd->baseClass->ctor)
955 {
956 sc2->callSuper = 0;
957
958 // Insert implicit super() at start of fbody
959 Expression *e1 = new SuperExp(0);
960 Expression *e = new CallExp(0, e1);
961
962 unsigned errors = global.errors;
963 global.gag++;
964 e = e->semantic(sc2);
965 global.gag--;
966 if (errors != global.errors)
967 error("no match for implicit super() call in constructor");
968
969 Statement *s = new ExpStatement(0, e);
970 fbody = new CompoundStatement(0, s, fbody);
971 }
972 }
973 else if (fes)
974 { // For foreach(){} body, append a return 0;
975 Expression *e = new IntegerExp(0);
976 Statement *s = new ReturnStatement(0, e);
977 fbody = new CompoundStatement(0, fbody, s);
978 assert(!returnLabel);
979 }
980 else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
981 error("expected to return a value of type %s", type->nextOf()->toChars());
982 else if (!inlineAsm)
983 {
984 if (type->nextOf()->ty == Tvoid)
985 {
986 if (offend && isMain())
987 { // Add a return 0; statement
988 Statement *s = new ReturnStatement(0, new IntegerExp(0));
989 fbody = new CompoundStatement(0, fbody, s);
990 }
991 }
992 else
993 {
994 if (offend)
995 { Expression *e;
996
997 if (global.params.warnings)
998 { fprintf(stdmsg, "warning - ");
999 error("no return at end of function");
1000 }
1001
1002 if (global.params.useAssert &&
1003 !global.params.useInline)
1004 { /* Add an assert(0, msg); where the missing return
1005 * should be.
1006 */
1007 e = new AssertExp(
1008 endloc,
1009 new IntegerExp(0),
1010 new StringExp(loc, "missing return expression")
1011 );
1012 }
1013 else
1014 e = new HaltExp(endloc);
1015 e = new CommaExp(0, e, type->nextOf()->defaultInit());
1016 e = e->semantic(sc2);
1017 Statement *s = new ExpStatement(0, e);
1018 fbody = new CompoundStatement(0, fbody, s);
1019 }
1020 }
1021 }
1022 }
1023
1024 {
1025 Statements *a = new Statements();
1026
1027 // Merge in initialization of 'out' parameters
1028 if (parameters)
1029 { for (size_t i = 0; i < parameters->dim; i++)
1030 { VarDeclaration *v;
1031
1032 v = (VarDeclaration *)parameters->data[i];
1033 if (v->storage_class & STCout)
1034 {
1035 assert(v->init);
1036 ExpInitializer *ie = v->init->isExpInitializer();
1037 assert(ie);
1038 a->push(new ExpStatement(0, ie->exp));
1039 }
1040 }
1041 }
1042
1043 if (argptr)
1044 { // Initialize _argptr to point past non-variadic arg
1045 #if IN_GCC
1046 // Handled in FuncDeclaration::toObjFile
1047 v_argptr = argptr;
1048 v_argptr->init = new VoidInitializer(loc);
1049 #else
1050 Expression *e1;
1051 Expression *e;
1052 Type *t = argptr->type;
1053 VarDeclaration *p;
1054 unsigned offset;
1055
1056 e1 = new VarExp(0, argptr);
1057 if (parameters && parameters->dim)
1058 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1059 else
1060 p = v_arguments; // last parameter is _arguments[]
1061 offset = p->type->size();
1062 offset = (offset + 3) & ~3; // assume stack aligns on 4
1063 e = new SymOffExp(0, p, offset);
1064 e = new AssignExp(0, e1, e);
1065 e->type = t;
1066 a->push(new ExpStatement(0, e));
1067 #endif
1068 }
1069
1070 if (_arguments)
1071 {
1072 /* Advance to elements[] member of TypeInfo_Tuple with:
1073 * _arguments = v_arguments.elements;
1074 */
1075 Expression *e = new VarExp(0, v_arguments);
1076 e = new DotIdExp(0, e, Id::elements);
1077 Expression *e1 = new VarExp(0, _arguments);
1078 e = new AssignExp(0, e1, e);
1079 e = e->semantic(sc);
1080 a->push(new ExpStatement(0, e));
1081 }
1082
1083 // Merge contracts together with body into one compound statement
1084
1085 #ifdef _DH
1086 if (frequire && global.params.useIn)
1087 { frequire->incontract = 1;
1088 a->push(frequire);
1089 }
1090 #else
1091 if (frequire && global.params.useIn)
1092 a->push(frequire);
1093 #endif
1094
1095 // Precondition invariant
1096 if (addPreInvariant())
1097 {
1098 Expression *e = NULL;
1099 if (isDtorDeclaration())
1100 {
1101 // Call invariant directly only if it exists
1102 InvariantDeclaration *inv = ad->inv;
1103 ClassDeclaration *cd = ad->isClassDeclaration();
1104
1105 while (!inv && cd)
1106 {
1107 cd = cd->baseClass;
1108 if (!cd)
1109 break;
1110 inv = cd->inv;
1111 }
1112 if (inv)
1113 {
1114 e = new DsymbolExp(0, inv);
1115 e = new CallExp(0, e);
1116 e = e->semantic(sc2);
1117 }
1118 }
1119 else
1120 { // Call invariant virtually
1121 ThisExp *v = new ThisExp(0);
1122 v->type = vthis->type;
1123 Expression *se = new StringExp(0, "null this");
1124 se = se->semantic(sc);
1125 se->type = Type::tchar->arrayOf();
1126 e = new AssertExp(loc, v, se);
1127 }
1128 if (e)
1129 {
1130 ExpStatement *s = new ExpStatement(0, e);
1131 a->push(s);
1132 }
1133 }
1134
1135 if (fbody)
1136 a->push(fbody);
1137
1138 if (fensure)
1139 {
1140 a->push(returnLabel->statement);
1141
1142 if (type->nextOf()->ty != Tvoid)
1143 {
1144 // Create: return vresult;
1145 assert(vresult);
1146 Expression *e = new VarExp(0, vresult);
1147 if (tintro)
1148 { e = e->implicitCastTo(sc, tintro->nextOf());
1149 e = e->semantic(sc);
1150 }
1151 ReturnStatement *s = new ReturnStatement(0, e);
1152 a->push(s);
1153 }
1154 }
1155
1156 fbody = new CompoundStatement(0, a);
1157 }
1158
1159 sc2->callSuper = 0;
1160 sc2->pop();
1161 }
1162 semanticRun = 2;
1163 }
1164
1165 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1166 {
1167 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1168
1169 type->toCBuffer(buf, ident, hgs);
1170 bodyToCBuffer(buf, hgs);
1171 }
1172
1173
1174 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1175 {
1176 if (fbody &&
1177 (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1178 )
1179 { buf->writenl();
1180
1181 // in{}
1182 if (frequire)
1183 { buf->writestring("in");
1184 buf->writenl();
1185 frequire->toCBuffer(buf, hgs);
1186 }
1187
1188 // out{}
1189 if (fensure)
1190 { buf->writestring("out");
1191 if (outId)
1192 { buf->writebyte('(');
1193 buf->writestring(outId->toChars());
1194 buf->writebyte(')');
1195 }
1196 buf->writenl();
1197 fensure->toCBuffer(buf, hgs);
1198 }
1199
1200 if (frequire || fensure)
1201 { buf->writestring("body");
1202 buf->writenl();
1203 }
1204
1205 buf->writebyte('{');
1206 buf->writenl();
1207 fbody->toCBuffer(buf, hgs);
1208 buf->writebyte('}');
1209 buf->writenl();
1210 }
1211 else
1212 { buf->writeByte(';');
1213 buf->writenl();
1214 }
1215 }
1216
1217 /****************************************************
1218 * Determine if 'this' overrides fd.
1219 * Return !=0 if it does.
1220 */
1221
1222 int FuncDeclaration::overrides(FuncDeclaration *fd)
1223 { int result = 0;
1224
1225 if (fd->ident == ident)
1226 {
1227 int cov = type->covariant(fd->type);
1228 if (cov)
1229 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1230 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1231
1232 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1233 result = 1;
1234 }
1235 }
1236 return result;
1237 }
1238
1239 /****************************************************
1240 * Overload this FuncDeclaration with the new one f.
1241 * Return !=0 if successful; i.e. no conflict.
1242 */
1243
1244 int FuncDeclaration::overloadInsert(Dsymbol *s)
1245 {
1246 FuncDeclaration *f;
1247 AliasDeclaration *a;
1248
1249 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1250 a = s->isAliasDeclaration();
1251 if (a)
1252 {
1253 if (overnext)
1254 return overnext->overloadInsert(a);
1255 if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1256 {
1257 //printf("\ta = '%s'\n", a->type->toChars());
1258 return FALSE;
1259 }
1260 overnext = a;
1261 //printf("\ttrue: no conflict\n");
1262 return TRUE;
1263 }
1264 f = s->isFuncDeclaration();
1265 if (!f)
1266 return FALSE;
1267
1268 if (type && f->type && // can be NULL for overloaded constructors
1269 f->type->covariant(type) &&
1270 !isFuncAliasDeclaration())
1271 {
1272 //printf("\tfalse: conflict %s\n", kind());
1273 return FALSE;
1274 }
1275
1276 if (overnext)
1277 return overnext->overloadInsert(f);
1278 overnext = f;
1279 //printf("\ttrue: no conflict\n");
1280 return TRUE;
1281 }
1282
1283 /********************************************
1284 * Find function in overload list that exactly matches t.
1285 */
1286
1287 /***************************************************
1288 * Visit each overloaded function in turn, and call
1289 * (*fp)(param, f) on it.
1290 * Exit when no more, or (*fp)(param, f) returns 1.
1291 * Returns:
1292 * 0 continue
1293 * 1 done
1294 */
1295
1296 int overloadApply(FuncDeclaration *fstart,
1297 int (*fp)(void *, FuncDeclaration *),
1298 void *param)
1299 {
1300 FuncDeclaration *f;
1301 Declaration *d;
1302 Declaration *next;
1303
1304 for (d = fstart; d; d = next)
1305 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1306
1307 if (fa)
1308 {
1309 if (overloadApply(fa->funcalias, fp, param))
1310 return 1;
1311 next = fa->overnext;
1312 }
1313 else
1314 {
1315 AliasDeclaration *a = d->isAliasDeclaration();
1316
1317 if (a)
1318 {
1319 Dsymbol *s = a->toAlias();
1320 next = s->isDeclaration();
1321 if (next == a)
1322 break;
1323 if (next == fstart)
1324 break;
1325 }
1326 else
1327 {
1328 f = d->isFuncDeclaration();
1329 if (!f)
1330 { d->error("is aliased to a function");
1331 break; // BUG: should print error message?
1332 }
1333 if ((*fp)(param, f))
1334 return 1;
1335
1336 next = f->overnext;
1337 }
1338 }
1339 }
1340 return 0;
1341 }
1342
1343 /********************************************
1344 * Find function in overload list that exactly matches t.
1345 */
1346
1347 struct Param1
1348 {
1349 Type *t; // type to match
1350 FuncDeclaration *f; // return value
1351 };
1352
1353 int fp1(void *param, FuncDeclaration *f)
1354 { Param1 *p = (Param1 *)param;
1355 Type *t = p->t;
1356
1357 if (t->equals(f->type))
1358 { p->f = f;
1359 return 1;
1360 }
1361
1362 #if V2
1363 /* Allow covariant matches, if it's just a const conversion
1364 * of the return type
1365 */
1366 if (t->ty == Tfunction)
1367 { TypeFunction *tf = (TypeFunction *)f->type;
1368 if (tf->covariant(t) == 1 &&
1369 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
1370 {
1371 p->f = f;
1372 return 1;
1373 }
1374 }
1375 #endif
1376 return 0;
1377 }
1378
1379 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1380 {
1381 Param1 p;
1382 p.t = t;
1383 p.f = NULL;
1384 overloadApply(this, &fp1, &p);
1385 return p.f;
1386 }
1387
1388 #if 0
1389 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1390 {
1391 FuncDeclaration *f;
1392 Declaration *d;
1393 Declaration *next;
1394
1395 for (d = this; d; d = next)
1396 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1397
1398 if (fa)
1399 {
1400 FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t);
1401 if (f2)
1402 return f2;
1403 next = fa->overnext;
1404 }
1405 else
1406 {
1407 AliasDeclaration *a = d->isAliasDeclaration();
1408
1409 if (a)
1410 {
1411 Dsymbol *s = a->toAlias();
1412 next = s->isDeclaration();
1413 if (next == a)
1414 break;
1415 }
1416 else
1417 {
1418 f = d->isFuncDeclaration();
1419 if (!f)
1420 break; // BUG: should print error message?
1421 if (t->equals(d->type))
1422 return f;
1423 next = f->overnext;
1424 }
1425 }
1426 }
1427 return NULL;
1428 }
1429 #endif
1430
1431 /********************************************
1432 * Decide which function matches the arguments best.
1433 */
1434
1435 struct Param2
1436 {
1437 Match *m;
1438 Expressions *arguments;
1439 };
1440
1441 int fp2(void *param, FuncDeclaration *f)
1442 { Param2 *p = (Param2 *)param;
1443 Match *m = p->m;
1444 Expressions *arguments = p->arguments;
1445 MATCH match;
1446
1447 if (f != m->lastf) // skip duplicates
1448 {
1449 TypeFunction *tf;
1450
1451 m->anyf = f;
1452 tf = (TypeFunction *)f->type;
1453 match = (MATCH) tf->callMatch(arguments);
1454 //printf("match = %d\n", match);
1455 if (match != MATCHnomatch)
1456 {
1457 if (match > m->last)
1458 goto LfIsBetter;
1459
1460 if (match < m->last)
1461 goto LlastIsBetter;
1462
1463 /* See if one of the matches overrides the other.
1464 */
1465 if (m->lastf->overrides(f))
1466 goto LlastIsBetter;
1467 else if (f->overrides(m->lastf))
1468 goto LfIsBetter;
1469
1470 Lambiguous:
1471 m->nextf = f;
1472 m->count++;
1473 return 0;
1474
1475 LfIsBetter:
1476 m->last = match;
1477 m->lastf = f;
1478 m->count = 1;
1479 return 0;
1480
1481 LlastIsBetter:
1482 return 0;
1483 }
1484 }
1485 return 0;
1486 }
1487
1488
1489 void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
1490 {
1491 Param2 p;
1492 p.m = m;
1493 p.arguments = arguments;
1494 overloadApply(fstart, &fp2, &p);
1495 }
1496
1497 #if 0
1498 // Recursive helper function
1499
1500 void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
1501 {
1502 MATCH match;
1503 Declaration *d;
1504 Declaration *next;
1505
1506 for (d = fstart; d; d = next)
1507 {
1508 FuncDeclaration *f;
1509 FuncAliasDeclaration *fa;
1510 AliasDeclaration *a;
1511
1512 fa = d->isFuncAliasDeclaration();
1513 if (fa)
1514 {
1515 overloadResolveX(m, fa->funcalias, arguments);
1516 next = fa->overnext;
1517 }
1518 else if ((f = d->isFuncDeclaration()) != NULL)
1519 {
1520 next = f->overnext;
1521 if (f == m->lastf)
1522 continue; // skip duplicates
1523 else
1524 {
1525 TypeFunction *tf;
1526
1527 m->anyf = f;
1528 tf = (TypeFunction *)f->type;
1529 match = (MATCH) tf->callMatch(arguments);
1530 //printf("match = %d\n", match);
1531 if (match != MATCHnomatch)
1532 {
1533 if (match > m->last)
1534 goto LfIsBetter;
1535
1536 if (match < m->last)
1537 goto LlastIsBetter;
1538
1539 /* See if one of the matches overrides the other.
1540 */
1541 if (m->lastf->overrides(f))
1542 goto LlastIsBetter;
1543 else if (f->overrides(m->lastf))
1544 goto LfIsBetter;
1545
1546 Lambiguous:
1547 m->nextf = f;
1548 m->count++;
1549 continue;
1550
1551 LfIsBetter:
1552 m->last = match;
1553 m->lastf = f;
1554 m->count = 1;
1555 continue;
1556
1557 LlastIsBetter:
1558 continue;
1559 }
1560 }
1561 }
1562 else if ((a = d->isAliasDeclaration()) != NULL)
1563 {
1564 Dsymbol *s = a->toAlias();
1565 next = s->isDeclaration();
1566 if (next == a)
1567 break;
1568 if (next == fstart)
1569 break;
1570 }
1571 else
1572 { d->error("is aliased to a function");
1573 break;
1574 }
1575 }
1576 }
1577 #endif
1578
1579 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expressions *arguments)
1580 {
1581 TypeFunction *tf;
1582 Match m;
1583
1584 #if 0
1585 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1586 if (arguments)
1587 { int i;
1588
1589 for (i = 0; i < arguments->dim; i++)
1590 { Expression *arg;
1591
1592 arg = (Expression *)arguments->data[i];
1593 assert(arg->type);
1594 printf("\t%s: ", arg->toChars());
1595 arg->type->print();
1596 }
1597 }
1598 #endif
1599
1600 memset(&m, 0, sizeof(m));
1601 m.last = MATCHnomatch;
1602 overloadResolveX(&m, this, arguments);
1603
1604 if (m.count == 1) // exactly one match
1605 {
1606 return m.lastf;
1607 }
1608 else
1609 {
1610 OutBuffer buf;
1611
1612 if (arguments)
1613 {
1614 HdrGenState hgs;
1615
1616 argExpTypesToCBuffer(&buf, arguments, &hgs);
1617 }
1618
1619 if (m.last == MATCHnomatch)
1620 {
1621 tf = (TypeFunction *)type;
1622
1623 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1624 error(loc, "%s does not match parameter types (%s)",
1625 Argument::argsTypesToChars(tf->parameters, tf->varargs),
1626 buf.toChars());
1627 return m.anyf; // as long as it's not a FuncAliasDeclaration
1628 }
1629 else
1630 {
1631 #if 1
1632 TypeFunction *t1 = (TypeFunction *)m.lastf->type;
1633 TypeFunction *t2 = (TypeFunction *)m.nextf->type;
1634
1635 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1636 buf.toChars(),
1637 m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
1638 m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
1639 #else
1640 error(loc, "overloads %s and %s both match argument list for %s",
1641 m.lastf->type->toChars(),
1642 m.nextf->type->toChars(),
1643 m.lastf->toChars());
1644 #endif
1645 return m.lastf;
1646 }
1647 }
1648 }
1649
1650 /********************************
1651 * Labels are in a separate scope, one per function.
1652 */
1653
1654 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
1655 { Dsymbol *s;
1656
1657 if (!labtab)
1658 labtab = new DsymbolTable(); // guess we need one
1659
1660 s = labtab->lookup(ident);
1661 if (!s)
1662 {
1663 s = new LabelDsymbol(ident);
1664 labtab->insert(s);
1665 }
1666 return (LabelDsymbol *)s;
1667 }
1668
1669 AggregateDeclaration *FuncDeclaration::isThis()
1670 { AggregateDeclaration *ad;
1671
1672 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1673 ad = NULL;
1674 if ((storage_class & STCstatic) == 0)
1675 {
1676 ad = isMember2();
1677 }
1678 //printf("-FuncDeclaration::isThis() %p\n", ad);
1679 return ad;
1680 }
1681
1682 AggregateDeclaration *FuncDeclaration::isMember2()
1683 { AggregateDeclaration *ad;
1684
1685 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1686 ad = NULL;
1687 for (Dsymbol *s = this; s; s = s->parent)
1688 {
1689 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1690 ad = s->isMember();
1691 if (ad)
1692 { //printf("test4\n");
1693 break;
1694 }
1695 if (!s->parent ||
1696 (!s->parent->isTemplateInstance()))
1697 { //printf("test5\n");
1698 break;
1699 }
1700 }
1701 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1702 return ad;
1703 }
1704
1705 /*****************************************
1706 * Determine lexical level difference from 'this' to nested function 'fd'.
1707 * Error if this cannot call fd.
1708 * Returns:
1709 * 0 same level
1710 * -1 increase nesting by 1 (fd is nested within 'this')
1711 * >0 decrease nesting by number
1712 */
1713
1714 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
1715 { int level;
1716 Dsymbol *s;
1717 Dsymbol *fdparent;
1718
1719 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1720 fdparent = fd->toParent2();
1721 if (fdparent == this)
1722 return -1;
1723 s = this;
1724 level = 0;
1725 while (fd != s && fdparent != s->toParent2())
1726 {
1727 //printf("\ts = '%s'\n", s->toChars());
1728 FuncDeclaration *thisfd = s->isFuncDeclaration();
1729 if (thisfd)
1730 { if (!thisfd->isNested() && !thisfd->vthis)
1731 goto Lerr;
1732 }
1733 else
1734 {
1735 ClassDeclaration *thiscd = s->isClassDeclaration();
1736 if (thiscd)
1737 { if (!thiscd->isNested())
1738 goto Lerr;
1739 }
1740 else
1741 goto Lerr;
1742 }
1743
1744 s = s->toParent2();
1745 assert(s);
1746 level++;
1747 }
1748 return level;
1749
1750 Lerr:
1751 error(loc, "cannot access frame of function %s", fd->toChars());
1752 return 1;
1753 }
1754
1755 void FuncDeclaration::appendExp(Expression *e)
1756 { Statement *s;
1757
1758 s = new ExpStatement(0, e);
1759 appendState(s);
1760 }
1761
1762 void FuncDeclaration::appendState(Statement *s)
1763 { CompoundStatement *cs;
1764
1765 if (!fbody)
1766 { Statements *a;
1767
1768 a = new Statements();
1769 fbody = new CompoundStatement(0, a);
1770 }
1771 cs = fbody->isCompoundStatement();
1772 cs->statements->push(s);
1773 }
1774
1775
1776 int FuncDeclaration::isMain()
1777 {
1778 return ident == Id::main &&
1779 linkage != LINKc && !isMember() && !isNested();
1780 }
1781
1782 int FuncDeclaration::isWinMain()
1783 {
1784 return ident == Id::WinMain &&
1785 linkage != LINKc && !isMember();
1786 }
1787
1788 int FuncDeclaration::isDllMain()
1789 {
1790 return ident == Id::DllMain &&
1791 linkage != LINKc && !isMember();
1792 }
1793
1794 int FuncDeclaration::isExport()
1795 {
1796 return protection == PROTexport;
1797 }
1798
1799 int FuncDeclaration::isImportedSymbol()
1800 {
1801 //printf("isImportedSymbol()\n");
1802 //printf("protection = %d\n", protection);
1803 return (protection == PROTexport) && !fbody;
1804 }
1805
1806 // Determine if function goes into virtual function pointer table
1807
1808 int FuncDeclaration::isVirtual()
1809 {
1810 #if 0
1811 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1812 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
1813 printf("result is %d\n",
1814 isMember() &&
1815 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1816 toParent()->isClassDeclaration());
1817 #endif
1818 return isMember() &&
1819 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1820 toParent()->isClassDeclaration();
1821 }
1822
1823 int FuncDeclaration::isAbstract()
1824 {
1825 return storage_class & STCabstract;
1826 }
1827
1828 int FuncDeclaration::isCodeseg()
1829 {
1830 return TRUE; // functions are always in the code segment
1831 }
1832
1833 // Determine if function needs
1834 // a static frame pointer to its lexically enclosing function
1835
1836 int FuncDeclaration::isNested()
1837 {
1838 //if (!toParent())
1839 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
1840 //printf("\ttoParent() = '%s'\n", toParent()->toChars());
1841 return ((storage_class & STCstatic) == 0) &&
1842 (toParent2()->isFuncDeclaration() != NULL);
1843 }
1844
1845 int FuncDeclaration::needThis()
1846 {
1847 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
1848 int i = isThis() != NULL;
1849 //printf("\t%d\n", i);
1850 if (!i && isFuncAliasDeclaration())
1851 i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
1852 return i;
1853 }
1854
1855 int FuncDeclaration::addPreInvariant()
1856 {
1857 AggregateDeclaration *ad = isThis();
1858 return (ad &&
1859 //ad->isClassDeclaration() &&
1860 global.params.useInvariants &&
1861 (protection == PROTpublic || protection == PROTexport) &&
1862 !naked);
1863 }
1864
1865 int FuncDeclaration::addPostInvariant()
1866 {
1867 AggregateDeclaration *ad = isThis();
1868 return (ad &&
1869 ad->inv &&
1870 //ad->isClassDeclaration() &&
1871 global.params.useInvariants &&
1872 (protection == PROTpublic || protection == PROTexport) &&
1873 !naked);
1874 }
1875
1876 /**********************************
1877 * Generate a FuncDeclaration for a runtime library function.
1878 */
1879
1880 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name)
1881 {
1882 return genCfunc(treturn, Lexer::idPool(name));
1883 }
1884
1885 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id)
1886 {
1887 FuncDeclaration *fd;
1888 TypeFunction *tf;
1889 Dsymbol *s;
1890 static DsymbolTable *st = NULL;
1891
1892 //printf("genCfunc(name = '%s')\n", id->toChars());
1893 //printf("treturn\n\t"); treturn->print();
1894
1895 // See if already in table
1896 if (!st)
1897 st = new DsymbolTable();
1898 s = st->lookup(id);
1899 if (s)
1900 {
1901 fd = s->isFuncDeclaration();
1902 assert(fd);
1903 assert(fd->type->nextOf()->equals(treturn));
1904 }
1905 else
1906 {
1907 tf = new TypeFunction(NULL, treturn, 0, LINKc);
1908 fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
1909 fd->protection = PROTpublic;
1910 fd->linkage = LINKc;
1911
1912 st->insert(fd);
1913 }
1914 return fd;
1915 }
1916
1917 char *FuncDeclaration::kind()
1918 {
1919 return "function";
1920 }
1921
1922 /****************************** FuncAliasDeclaration ************************/
1923
1924 // Used as a way to import a set of functions from another scope into this one.
1925
1926 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
1927 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
1928 (enum STC)funcalias->storage_class, funcalias->type)
1929 {
1930 assert(funcalias != this);
1931 this->funcalias = funcalias;
1932 }
1933
1934 char *FuncAliasDeclaration::kind()
1935 {
1936 return "function alias";
1937 }
1938
1939
1940 /****************************** FuncLiteralDeclaration ************************/
1941
1942 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
1943 enum TOK tok, ForeachStatement *fes)
1944 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
1945 {
1946 char *id;
1947
1948 if (fes)
1949 id = "__foreachbody";
1950 else if (tok == TOKdelegate)
1951 id = "__dgliteral";
1952 else
1953 id = "__funcliteral";
1954 this->ident = Identifier::generateId(id);
1955 this->tok = tok;
1956 this->fes = fes;
1957 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
1958 }
1959
1960 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
1961 {
1962 FuncLiteralDeclaration *f;
1963
1964 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
1965 if (s)
1966 f = (FuncLiteralDeclaration *)s;
1967 else
1968 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
1969 FuncDeclaration::syntaxCopy(f);
1970 return f;
1971 }
1972
1973 int FuncLiteralDeclaration::isNested()
1974 {
1975 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
1976 return (tok == TOKdelegate);
1977 }
1978
1979 char *FuncLiteralDeclaration::kind()
1980 {
1981 // GCC requires the (char*) casts
1982 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
1983 }
1984
1985 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1986 {
1987 static Identifier *idfunc;
1988 static Identifier *iddel;
1989
1990 if (!idfunc)
1991 idfunc = new Identifier("function", 0);
1992 if (!iddel)
1993 iddel = new Identifier("delegate", 0);
1994
1995 type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
1996 bodyToCBuffer(buf, hgs);
1997 }
1998
1999
2000 /********************************* CtorDeclaration ****************************/
2001
2002 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2003 : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
2004 {
2005 this->arguments = arguments;
2006 this->varargs = varargs;
2007 //printf("CtorDeclaration() %s\n", toChars());
2008 }
2009
2010 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2011 {
2012 CtorDeclaration *f;
2013
2014 f = new CtorDeclaration(loc, endloc, NULL, varargs);
2015
2016 f->outId = outId;
2017 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2018 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
2019 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
2020 assert(!fthrows); // deprecated
2021
2022 f->arguments = Argument::arraySyntaxCopy(arguments);
2023 return f;
2024 }
2025
2026
2027 void CtorDeclaration::semantic(Scope *sc)
2028 {
2029 ClassDeclaration *cd;
2030 Type *tret;
2031
2032 //printf("CtorDeclaration::semantic()\n");
2033
2034 sc = sc->push();
2035 sc->stc &= ~STCstatic; // not a static constructor
2036
2037 parent = sc->parent;
2038 Dsymbol *parent = toParent();
2039 cd = parent->isClassDeclaration();
2040 if (!cd)
2041 {
2042 error("constructors only are for class definitions");
2043 tret = Type::tvoid;
2044 }
2045 else
2046 tret = cd->type; //->referenceTo();
2047 type = new TypeFunction(arguments, tret, varargs, LINKd);
2048
2049 sc->flags |= SCOPEctor;
2050 type = type->semantic(loc, sc);
2051 sc->flags &= ~SCOPEctor;
2052
2053 // Append:
2054 // return this;
2055 // to the function body
2056 if (fbody)
2057 { Expression *e;
2058 Statement *s;
2059
2060 e = new ThisExp(0);
2061 s = new ReturnStatement(0, e);
2062 fbody = new CompoundStatement(0, fbody, s);
2063 }
2064
2065 FuncDeclaration::semantic(sc);
2066
2067 sc->pop();
2068
2069 // See if it's the default constructor
2070 if (cd && varargs == 0 && Argument::dim(arguments) == 0)
2071 cd->defaultCtor = this;
2072 }
2073
2074 char *CtorDeclaration::kind()
2075 {
2076 return "constructor";
2077 }
2078
2079 char *CtorDeclaration::toChars()
2080 {
2081 return "this";
2082 }
2083
2084 int CtorDeclaration::isVirtual()
2085 {
2086 return FALSE;
2087 }
2088
2089 int CtorDeclaration::addPreInvariant()
2090 {
2091 return FALSE;
2092 }
2093
2094 int CtorDeclaration::addPostInvariant()
2095 {
2096 return (vthis && global.params.useInvariants);
2097 }
2098
2099
2100 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2101 {
2102 buf->writestring("this");
2103 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2104 bodyToCBuffer(buf, hgs);
2105 }
2106
2107 /********************************* DtorDeclaration ****************************/
2108
2109 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
2110 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
2111 {
2112 }
2113
2114 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
2115 {
2116 DtorDeclaration *dd;
2117
2118 assert(!s);
2119 dd = new DtorDeclaration(loc, endloc);
2120 return FuncDeclaration::syntaxCopy(dd);
2121 }
2122
2123
2124 void DtorDeclaration::semantic(Scope *sc)
2125 {
2126 ClassDeclaration *cd;
2127
2128 parent = sc->parent;
2129 Dsymbol *parent = toParent();
2130 cd = parent->isClassDeclaration();
2131 if (!cd)
2132 {
2133 error("destructors only are for class definitions");
2134 }
2135 else
2136 cd->dtors.push(this);
2137 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2138
2139 sc = sc->push();
2140 sc->stc &= ~STCstatic; // not a static destructor
2141 sc->linkage = LINKd;
2142
2143 FuncDeclaration::semantic(sc);
2144
2145 sc->pop();
2146 }
2147
2148 int DtorDeclaration::overloadInsert(Dsymbol *s)
2149 {
2150 return FALSE; // cannot overload destructors
2151 }
2152
2153 int DtorDeclaration::addPreInvariant()
2154 {
2155 return (vthis && global.params.useInvariants);
2156 }
2157
2158 int DtorDeclaration::addPostInvariant()
2159 {
2160 return FALSE;
2161 }
2162
2163 int DtorDeclaration::isVirtual()
2164 {
2165 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2166 * but doing so will require recompiling everything.
2167 */
2168 #if BREAKABI
2169 return FALSE;
2170 #else
2171 return FuncDeclaration::isVirtual();
2172 #endif
2173 }
2174
2175 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2176 {
2177 if (hgs->hdrgen)
2178 return;
2179 buf->writestring("~this()");
2180 bodyToCBuffer(buf, hgs);
2181 }
2182
2183 /********************************* StaticCtorDeclaration ****************************/
2184
2185 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
2186 : FuncDeclaration(loc, endloc, Id::staticCtor, STCstatic, NULL)
2187 {
2188 }
2189
2190 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
2191 {
2192 StaticCtorDeclaration *scd;
2193
2194 assert(!s);
2195 scd = new StaticCtorDeclaration(loc, endloc);
2196 return FuncDeclaration::syntaxCopy(scd);
2197 }
2198
2199
2200 void StaticCtorDeclaration::semantic(Scope *sc)
2201 {
2202 //printf("StaticCtorDeclaration::semantic()\n");
2203
2204 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2205
2206 FuncDeclaration::semantic(sc);
2207
2208 // We're going to need ModuleInfo
2209 Module *m = getModule();
2210 if (!m)
2211 m = sc->module;
2212 if (m)
2213 { m->needmoduleinfo = 1;
2214 #ifdef IN_GCC
2215 m->strictlyneedmoduleinfo = 1;
2216 #endif
2217 }
2218 }
2219
2220 AggregateDeclaration *StaticCtorDeclaration::isThis()
2221 {
2222 return NULL;
2223 }
2224
2225 int StaticCtorDeclaration::isStaticConstructor()
2226 {
2227 return TRUE;
2228 }
2229
2230 int StaticCtorDeclaration::isVirtual()
2231 {
2232 return FALSE;
2233 }
2234
2235 int StaticCtorDeclaration::addPreInvariant()
2236 {
2237 return FALSE;
2238 }
2239
2240 int StaticCtorDeclaration::addPostInvariant()
2241 {
2242 return FALSE;
2243 }
2244
2245 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2246 {
2247 if (hgs->hdrgen)
2248 { buf->writestring("static this(){}\n");
2249 return;
2250 }
2251 buf->writestring("static this()");
2252 bodyToCBuffer(buf, hgs);
2253 }
2254
2255 /********************************* StaticDtorDeclaration ****************************/
2256
2257 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
2258 : FuncDeclaration(loc, endloc, Id::staticDtor, STCstatic, NULL)
2259 {
2260 }
2261
2262 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
2263 {
2264 StaticDtorDeclaration *sdd;
2265
2266 assert(!s);
2267 sdd = new StaticDtorDeclaration(loc, endloc);
2268 return FuncDeclaration::syntaxCopy(sdd);
2269 }
2270
2271
2272 void StaticDtorDeclaration::semantic(Scope *sc)
2273 {
2274 ClassDeclaration *cd;
2275 Type *tret;
2276
2277 cd = sc->scopesym->isClassDeclaration();
2278 if (!cd)
2279 {
2280 }
2281 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2282
2283 FuncDeclaration::semantic(sc);
2284
2285 // We're going to need ModuleInfo
2286 Module *m = getModule();
2287 if (!m)
2288 m = sc->module;
2289 if (m)
2290 { m->needmoduleinfo = 1;
2291 #ifdef IN_GCC
2292 m->strictlyneedmoduleinfo = 1;
2293 #endif
2294 }
2295 }
2296
2297 AggregateDeclaration *StaticDtorDeclaration::isThis()
2298 {
2299 return NULL;
2300 }
2301
2302 int StaticDtorDeclaration::isStaticDestructor()
2303 {
2304 return TRUE;
2305 }
2306
2307 int StaticDtorDeclaration::isVirtual()
2308 {
2309 return FALSE;
2310 }
2311
2312 int StaticDtorDeclaration::addPreInvariant()
2313 {
2314 return FALSE;
2315 }
2316
2317 int StaticDtorDeclaration::addPostInvariant()
2318 {
2319 return FALSE;
2320 }
2321
2322 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2323 {
2324 if (hgs->hdrgen)
2325 return;
2326 buf->writestring("static ~this()");
2327 bodyToCBuffer(buf, hgs);
2328 }
2329
2330 /********************************* InvariantDeclaration ****************************/
2331
2332 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
2333 : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
2334 {
2335 }
2336
2337 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
2338 {
2339 InvariantDeclaration *id;
2340
2341 assert(!s);
2342 id = new InvariantDeclaration(loc, endloc);
2343 FuncDeclaration::syntaxCopy(id);
2344 return id;
2345 }
2346
2347
2348 void InvariantDeclaration::semantic(Scope *sc)
2349 {
2350 AggregateDeclaration *ad;
2351 Type *tret;
2352
2353 parent = sc->parent;
2354 Dsymbol *parent = toParent();
2355 ad = parent->isAggregateDeclaration();
2356 if (!ad)
2357 {
2358 error("invariants only are for struct/union/class definitions");
2359 return;
2360 }
2361 else if (ad->inv && ad->inv != this)
2362 {
2363 error("more than one invariant for %s", ad->toChars());
2364 }
2365 ad->inv = this;
2366 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2367
2368 sc = sc->push();
2369 sc->stc &= ~STCstatic; // not a static invariant
2370 sc->incontract++;
2371 sc->linkage = LINKd;
2372
2373 FuncDeclaration::semantic(sc);
2374
2375 sc->pop();
2376 }
2377
2378 int InvariantDeclaration::isVirtual()
2379 {
2380 return FALSE;
2381 }
2382
2383 int InvariantDeclaration::addPreInvariant()
2384 {
2385 return FALSE;
2386 }
2387
2388 int InvariantDeclaration::addPostInvariant()
2389 {
2390 return FALSE;
2391 }
2392
2393 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2394 {
2395 if (hgs->hdrgen)
2396 return;
2397 buf->writestring("invariant");
2398 bodyToCBuffer(buf, hgs);
2399 }
2400
2401
2402 /********************************* UnitTestDeclaration ****************************/
2403
2404 /*******************************
2405 * Generate unique unittest function Id so we can have multiple
2406 * instances per module.
2407 */
2408
2409 static Identifier *unitTestId()
2410 {
2411 static int n;
2412 char buffer[10 + sizeof(n)*3 + 1];
2413
2414 sprintf(buffer,"__unittest%d", n);
2415 n++;
2416 return Lexer::idPool(buffer);
2417 }
2418
2419 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
2420 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
2421 {
2422 }
2423
2424 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
2425 {
2426 UnitTestDeclaration *utd;
2427
2428 assert(!s);
2429 utd = new UnitTestDeclaration(loc, endloc);
2430 return FuncDeclaration::syntaxCopy(utd);
2431 }
2432
2433
2434 void UnitTestDeclaration::semantic(Scope *sc)
2435 {
2436 if (global.params.useUnitTests)
2437 {
2438 Type *tret;
2439
2440 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2441 FuncDeclaration::semantic(sc);
2442 }
2443
2444 // We're going to need ModuleInfo even if the unit tests are not
2445 // compiled in, because other modules may import this module and refer
2446 // to this ModuleInfo.
2447 Module *m = getModule();
2448 if (!m)
2449 m = sc->module;
2450 if (m)
2451 m->needmoduleinfo = 1;
2452 }
2453
2454 AggregateDeclaration *UnitTestDeclaration::isThis()
2455 {
2456 return NULL;
2457 }
2458
2459 int UnitTestDeclaration::isVirtual()
2460 {
2461 return FALSE;
2462 }
2463
2464 int UnitTestDeclaration::addPreInvariant()
2465 {
2466 return FALSE;
2467 }
2468
2469 int UnitTestDeclaration::addPostInvariant()
2470 {
2471 return FALSE;
2472 }
2473
2474 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2475 {
2476 if (hgs->hdrgen)
2477 return;
2478 buf->writestring("unittest");
2479 bodyToCBuffer(buf, hgs);
2480 }
2481
2482 /********************************* NewDeclaration ****************************/
2483
2484 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2485 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
2486 {
2487 this->arguments = arguments;
2488 this->varargs = varargs;
2489 }
2490
2491 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
2492 {
2493 NewDeclaration *f;
2494
2495 f = new NewDeclaration(loc, endloc, NULL, varargs);
2496
2497 FuncDeclaration::syntaxCopy(f);
2498
2499 f->arguments = Argument::arraySyntaxCopy(arguments);
2500
2501 return f;
2502 }
2503
2504
2505 void NewDeclaration::semantic(Scope *sc)
2506 {
2507 ClassDeclaration *cd;
2508 Type *tret;
2509
2510 //printf("NewDeclaration::semantic()\n");
2511
2512 parent = sc->parent;
2513 Dsymbol *parent = toParent();
2514 cd = parent->isClassDeclaration();
2515 if (!cd && !parent->isStructDeclaration())
2516 {
2517 error("new allocators only are for class or struct definitions");
2518 }
2519 tret = Type::tvoid->pointerTo();
2520 type = new TypeFunction(arguments, tret, varargs, LINKd);
2521
2522 type = type->semantic(loc, sc);
2523 assert(type->ty == Tfunction);
2524
2525 // Check that there is at least one argument of type uint
2526 TypeFunction *tf = (TypeFunction *)type;
2527 if (Argument::dim(tf->parameters) < 1)
2528 {
2529 error("at least one argument of type uint expected");
2530 }
2531 else
2532 {
2533 Argument *a = Argument::getNth(tf->parameters, 0);
2534 if (!a->type->equals(Type::tuns32))
2535 error("first argument must be type uint, not %s", a->type->toChars());
2536 }
2537
2538 FuncDeclaration::semantic(sc);
2539 }
2540
2541 char *NewDeclaration::kind()
2542 {
2543 return "allocator";
2544 }
2545
2546 int NewDeclaration::isVirtual()
2547 {
2548 return FALSE;
2549 }
2550
2551 int NewDeclaration::addPreInvariant()
2552 {
2553 return FALSE;
2554 }
2555
2556 int NewDeclaration::addPostInvariant()
2557 {
2558 return FALSE;
2559 }
2560
2561 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2562 {
2563 buf->writestring("new");
2564 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2565 bodyToCBuffer(buf, hgs);
2566 }
2567
2568
2569 /********************************* DeleteDeclaration ****************************/
2570
2571 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
2572 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
2573 {
2574 this->arguments = arguments;
2575 }
2576
2577 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
2578 {
2579 DeleteDeclaration *f;
2580
2581 f = new DeleteDeclaration(loc, endloc, NULL);
2582
2583 FuncDeclaration::syntaxCopy(f);
2584
2585 f->arguments = Argument::arraySyntaxCopy(arguments);
2586
2587 return f;
2588 }
2589
2590
2591 void DeleteDeclaration::semantic(Scope *sc)
2592 {
2593 ClassDeclaration *cd;
2594
2595 //printf("DeleteDeclaration::semantic()\n");
2596
2597 parent = sc->parent;
2598 Dsymbol *parent = toParent();
2599 cd = parent->isClassDeclaration();
2600 if (!cd && !parent->isStructDeclaration())
2601 {
2602 error("new allocators only are for class or struct definitions");
2603 }
2604 type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
2605
2606 type = type->semantic(loc, sc);
2607 assert(type->ty == Tfunction);
2608
2609 // Check that there is only one argument of type void*
2610 TypeFunction *tf = (TypeFunction *)type;
2611 if (Argument::dim(tf->parameters) != 1)
2612 {
2613 error("one argument of type void* expected");
2614 }
2615 else
2616 {
2617 Argument *a = Argument::getNth(tf->parameters, 0);
2618 if (!a->type->equals(Type::tvoid->pointerTo()))
2619 error("one argument of type void* expected, not %s", a->type->toChars());
2620 }
2621
2622 FuncDeclaration::semantic(sc);
2623 }
2624
2625 char *DeleteDeclaration::kind()
2626 {
2627 return "deallocator";
2628 }
2629
2630 int DeleteDeclaration::isDelete()
2631 {
2632 return TRUE;
2633 }
2634
2635 int DeleteDeclaration::isVirtual()
2636 {
2637 return FALSE;
2638 }
2639
2640 int DeleteDeclaration::addPreInvariant()
2641 {
2642 return FALSE;
2643 }
2644
2645 int DeleteDeclaration::addPostInvariant()
2646 {
2647 return FALSE;
2648 }
2649
2650 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2651 {
2652 buf->writestring("delete");
2653 Argument::argsToCBuffer(buf, hgs, arguments, 0);
2654 bodyToCBuffer(buf, hgs);
2655 }
2656
2657
2658
2659