Skip not-null checks for _argptr and _arguments
[delight/core.git] / dmd / func.c
blobc692f73a4c4790ba70b2aafbf911cf9499f94081
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 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.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 #include <stdio.h>
18 #include <assert.h>
20 #include "mars.h"
21 #include "init.h"
22 #include "declaration.h"
23 #include "attrib.h"
24 #include "expression.h"
25 #include "scope.h"
26 #include "mtype.h"
27 #include "aggregate.h"
28 #include "identifier.h"
29 #include "id.h"
30 #include "module.h"
31 #include "statement.h"
32 #include "template.h"
33 #include "hdrgen.h"
35 #ifdef IN_GCC
36 #include "d-dmd-gcc.h"
37 #endif
39 /********************************* FuncDeclaration ****************************/
41 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
42 : Declaration(id)
44 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
45 this->storage_class = storage_class;
46 this->type = type;
47 this->loc = loc;
48 this->endloc = endloc;
49 fthrows = NULL;
50 frequire = NULL;
51 outId = NULL;
52 vresult = NULL;
53 returnLabel = NULL;
54 fensure = NULL;
55 fbody = NULL;
56 localsymtab = NULL;
57 vthis = NULL;
58 v_arguments = NULL;
59 #if IN_GCC
60 v_argptr = NULL;
61 v_arguments_var = NULL;
62 #endif
63 parameters = NULL;
64 labtab = NULL;
65 overnext = NULL;
66 vtblIndex = -1;
67 hasReturnExp = 0;
68 naked = 0;
69 inlineStatus = ILSuninitialized;
70 inlineNest = 0;
71 inlineAsm = 0;
72 cantInterpret = 0;
73 semanticRun = 0;
74 nestedFrameRef = 0;
75 fes = NULL;
76 introducing = 0;
77 tintro = NULL;
78 inferRetType = (type && type->nextOf() == NULL);
79 scope = NULL;
80 hasReturnExp = 0;
81 nrvo_can = 1;
82 nrvo_var = NULL;
83 shidden = NULL;
86 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
88 FuncDeclaration *f;
90 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
91 if (s)
92 f = (FuncDeclaration *)s;
93 else
94 f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
95 f->outId = outId;
96 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
97 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
98 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
99 assert(!fthrows); // deprecated
100 return f;
104 // Do the semantic analysis on the external interface to the function.
106 void FuncDeclaration::semantic(Scope *sc)
107 { TypeFunction *f;
108 StructDeclaration *sd;
109 ClassDeclaration *cd;
110 InterfaceDeclaration *id;
112 #if 0
113 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
114 if (isFuncLiteralDeclaration())
115 printf("\tFuncLiteralDeclaration()\n");
116 printf("sc->parent = %s\n", sc->parent->toChars());
117 printf("type: %s\n", type->toChars());
118 #endif
120 if (type->nextOf())
121 type = type->semantic(loc, sc);
122 //type->print();
123 if (type->ty != Tfunction)
125 error("%s must be a function", toChars());
126 return;
128 f = (TypeFunction *)(type);
129 size_t nparams = Argument::dim(f->parameters);
131 linkage = sc->linkage;
132 // if (!parent)
134 //parent = sc->scopesym;
135 parent = sc->parent;
137 protection = sc->protection;
138 storage_class |= sc->stc;
139 if (attributes)
140 attributes->append(sc->attributes);
141 else
142 attributes = sc->attributes;
143 //printf("function storage_class = x%x\n", storage_class);
144 Dsymbol *parent = toParent();
146 if (isConst() || isAuto() || isScope())
147 error("functions cannot be const or auto");
149 if (isAbstract() && !isVirtual())
150 error("non-virtual functions cannot be abstract");
152 if (isAbstract() && isFinal())
153 error("cannot be both final and abstract");
154 #if 0
155 if (isAbstract() && fbody)
156 error("abstract functions cannot have bodies");
157 #endif
159 #if 0
160 if (isStaticConstructor() || isStaticDestructor())
162 if (!isStatic() || type->nextOf()->ty != Tvoid)
163 error("static constructors / destructors must be static void");
164 if (f->arguments && f->arguments->dim)
165 error("static constructors / destructors must have empty parameter list");
166 // BUG: check for invalid storage classes
168 #endif
170 #ifdef IN_GCC
171 AggregateDeclaration *ad;
173 ad = parent->isAggregateDeclaration();
174 if (ad)
175 ad->methods.push(this);
176 #endif
177 sd = parent->isStructDeclaration();
178 if (sd)
180 // Verify no constructors, destructors, etc.
181 if (isCtorDeclaration() ||
182 isDtorDeclaration()
183 //|| isInvariantDeclaration()
184 //|| isUnitTestDeclaration()
187 error("special member functions not allowed for %ss", sd->kind());
190 #if 0
191 if (!sd->inv)
192 sd->inv = isInvariantDeclaration();
194 if (!sd->aggNew)
195 sd->aggNew = isNewDeclaration();
197 if (isDelete())
199 if (sd->aggDelete)
200 error("multiple delete's for struct %s", sd->toChars());
201 sd->aggDelete = (DeleteDeclaration *)(this);
203 #endif
206 id = parent->isInterfaceDeclaration();
207 if (id)
209 storage_class |= STCabstract;
211 if (isCtorDeclaration() ||
212 isDtorDeclaration() ||
213 isInvariantDeclaration() ||
214 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
215 error("special function not allowed in interface %s", id->toChars());
216 if (fbody)
217 error("function body is not abstract in interface %s", id->toChars());
220 cd = parent->isClassDeclaration();
221 if (cd)
222 { int vi;
223 CtorDeclaration *ctor;
224 DtorDeclaration *dtor;
225 InvariantDeclaration *inv;
227 if (isCtorDeclaration())
229 // ctor = (CtorDeclaration *)this;
230 // if (!cd->ctor)
231 // cd->ctor = ctor;
232 return;
235 #if 0
236 dtor = isDtorDeclaration();
237 if (dtor)
239 if (cd->dtor)
240 error("multiple destructors for class %s", cd->toChars());
241 cd->dtor = dtor;
244 inv = isInvariantDeclaration();
245 if (inv)
247 cd->inv = inv;
250 if (isNewDeclaration())
252 if (!cd->aggNew)
253 cd->aggNew = (NewDeclaration *)(this);
256 if (isDelete())
258 if (cd->aggDelete)
259 error("multiple delete's for class %s", cd->toChars());
260 cd->aggDelete = (DeleteDeclaration *)(this);
262 #endif
264 if (storage_class & STCabstract)
265 cd->isabstract = 1;
267 // if static function, do not put in vtbl[]
268 if (!isVirtual())
270 //printf("\tnot virtual\n");
271 goto Ldone;
274 // Find index of existing function in vtbl[] to override
275 vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
276 switch (vi)
278 case -1: // didn't find one
279 // This is an 'introducing' function.
281 // Verify this doesn't override previous final function
282 if (cd->baseClass)
283 { Dsymbol *s = cd->baseClass->search(loc, ident, 0);
284 if (s)
286 FuncDeclaration *f = s->isFuncDeclaration();
287 f = f->overloadExactMatch(type);
288 if (f && f->isFinal() && f->prot() != PROTprivate)
289 error("cannot override final function %s", f->toPrettyChars());
293 if (isFinal())
295 cd->vtblFinal.push(this);
297 else
299 // Append to end of vtbl[]
300 //printf("\tintroducing function\n");
301 introducing = 1;
302 vi = cd->vtbl.dim;
303 cd->vtbl.push(this);
304 vtblIndex = vi;
306 break;
308 case -2: // can't determine because of fwd refs
309 cd->sizeok = 2; // can't finish due to forward reference
310 return;
312 default:
313 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
314 // This function is covariant with fdv
315 if (fdv->isFinal())
316 error("cannot override final function %s", fdv->toPrettyChars());
318 #if V2
319 if (!isOverride() && global.params.warnings)
320 error("overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
321 #else
322 if (!isOverride() && sc->module->isDltFile)
323 error("overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
324 #endif
326 if (fdv->toParent() == parent)
328 // If both are mixins, then error.
329 // If either is not, the one that is not overrides
330 // the other.
331 if (fdv->parent->isClassDeclaration())
332 break;
333 if (!this->parent->isClassDeclaration()
334 #if !BREAKABI
335 && !isDtorDeclaration()
336 #endif
337 #if V2
338 && !isPostBlitDeclaration()
339 #endif
341 error("multiple overrides of same function");
343 cd->vtbl.data[vi] = (void *)this;
344 vtblIndex = vi;
346 /* This works by whenever this function is called,
347 * it actually returns tintro, which gets dynamically
348 * cast to type. But we know that tintro is a base
349 * of type, so we could optimize it by not doing a
350 * dynamic cast, but just subtracting the isBaseOf()
351 * offset if the value is != null.
354 if (fdv->tintro)
355 tintro = fdv->tintro;
356 else if (!type->equals(fdv->type))
358 /* Only need to have a tintro if the vptr
359 * offsets differ
361 target_ptrdiff_t offset;
362 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
364 tintro = fdv->type;
367 break;
371 /* Go through all the interface bases.
372 * If this function is covariant with any members of those interface
373 * functions, set the tintro.
375 for (int i = 0; i < cd->interfaces_dim; i++)
377 #if 1
378 BaseClass *b = cd->interfaces[i];
379 vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
380 switch (vi)
382 case -1:
383 break;
385 case -2:
386 cd->sizeok = 2; // can't finish due to forward reference
387 return;
389 default:
390 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
391 Type *ti = NULL;
393 if (fdv->tintro)
394 ti = fdv->tintro;
395 else if (!type->equals(fdv->type))
397 /* Only need to have a tintro if the vptr
398 * offsets differ
400 target_ptrdiff_t offset;
401 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
403 ti = fdv->type;
404 #if 0
405 if (offset)
406 ti = fdv->type;
407 else if (type->nextOf()->ty == Tclass)
408 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
409 if (cdn && cdn->sizeok != 1)
410 ti = fdv->type;
412 #endif
415 if (ti)
417 if (tintro && !tintro->equals(ti))
419 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
421 tintro = ti;
423 goto L2;
426 #else
427 BaseClass *b = cd->interfaces[i];
428 for (vi = 0; vi < b->base->vtbl.dim; vi++)
430 Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
431 //printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
432 FuncDeclaration *fdv = s->isFuncDeclaration();
433 if (fdv && fdv->ident == ident)
435 int cov = type->covariant(fdv->type);
436 //printf("\tcov = %d\n", cov);
437 if (cov == 2)
439 //type->print();
440 //fdv->type->print();
441 //printf("%s %s\n", type->deco, fdv->type->deco);
442 error("of type %s overrides but is not covariant with %s of type %s",
443 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
445 if (cov == 1)
446 { Type *ti = NULL;
448 if (fdv->tintro)
449 ti = fdv->tintro;
450 else if (!type->equals(fdv->type))
452 /* Only need to have a tintro if the vptr
453 * offsets differ
455 target_ptrdiff_t offset;
456 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
458 ti = fdv->type;
459 #if 0
460 if (offset)
461 ti = fdv->type;
462 else if (type->nextOf()->ty == Tclass)
463 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
464 if (cdn && cdn->sizeok != 1)
465 ti = fdv->type;
467 #endif
470 if (ti)
472 if (tintro && !tintro->equals(ti))
474 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
476 tintro = ti;
478 goto L2;
480 if (cov == 3)
482 cd->sizeok = 2; // can't finish due to forward reference
483 return;
487 #endif
490 if (introducing && isOverride())
492 error("does not override any function");
495 L2: ;
497 else if (isOverride() && !parent->isTemplateInstance())
498 error("override only applies to class member functions");
500 /* Do not allow template instances to add virtual functions
501 * to a class.
503 if (isVirtual())
505 TemplateInstance *ti = parent->isTemplateInstance();
506 if (ti)
508 // Take care of nested templates
509 while (1)
511 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
512 if (!ti2)
513 break;
514 ti = ti2;
517 // If it's a member template
518 ClassDeclaration *cd = ti->tempdecl->isClassMember();
519 if (cd)
521 error("cannot use template to add virtual function to class '%s'", cd->toChars());
526 if (isMain())
528 // Check parameters to see if they are either () or (char[][] args)
529 switch (nparams)
531 case 0:
532 break;
534 case 1:
536 Argument *arg0 = Argument::getNth(f->parameters, 0);
537 if (arg0->type->ty != Tarray ||
538 arg0->type->nextOf()->ty != Tarray ||
539 arg0->type->nextOf()->nextOf()->ty != Tchar ||
540 arg0->storageClass & (STCout | STCref | STClazy))
541 goto Lmainerr;
542 break;
545 default:
546 goto Lmainerr;
549 if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
550 error("must return int or void, not %s", f->nextOf()->toChars());
551 if (f->varargs)
553 Lmainerr:
554 error("parameters must be main() or main(char[][] args)");
558 if (ident == Id::assign && (sd || cd))
559 { // Disallow identity assignment operator.
561 // opAssign(...)
562 if (nparams == 0)
563 { if (f->varargs == 1)
564 goto Lassignerr;
566 else
568 Argument *arg0 = Argument::getNth(f->parameters, 0);
569 Type *t0 = arg0->type->toBasetype();
570 Type *tb = sd ? sd->type : cd->type;
571 if (arg0->type->implicitConvTo(tb) ||
572 (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
575 if (nparams == 1)
576 goto Lassignerr;
577 Argument *arg1 = Argument::getNth(f->parameters, 1);
578 if (arg1->defaultArg)
579 goto Lassignerr;
584 Ldone:
585 /* Save scope for possible later use (if we need the
586 * function internals)
588 scope = new Scope(*sc);
589 scope->setNoFree();
590 return;
592 Lassignerr:
593 error("identity assignment operator overload is illegal");
596 void FuncDeclaration::semantic2(Scope *sc)
600 // Do the semantic analysis on the internals of the function.
602 void FuncDeclaration::semantic3(Scope *sc)
603 { TypeFunction *f;
604 AggregateDeclaration *ad;
605 VarDeclaration *argptr = NULL;
606 VarDeclaration *_arguments = NULL;
608 if (!parent)
610 if (global.errors)
611 return;
612 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
613 assert(0);
615 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
616 //fflush(stdout);
617 //{ static int x; if (++x == 2) *(char*)0=0; }
618 //printf("\tlinkage = %d\n", sc->linkage);
620 //printf(" sc->incontract = %d\n", sc->incontract);
621 if (semanticRun)
622 return;
623 semanticRun = 1;
625 if (!type || type->ty != Tfunction)
626 return;
627 f = (TypeFunction *)(type);
628 size_t nparams = Argument::dim(f->parameters);
630 // Check the 'throws' clause
631 if (fthrows)
632 { int i;
634 for (i = 0; i < fthrows->dim; i++)
636 Type *t = (Type *)fthrows->data[i];
638 t = t->semantic(loc, sc);
639 if (!t->isClassHandle())
640 error("can only throw classes, not %s", t->toChars());
644 if (fbody || frequire)
646 /* Symbol table into which we place parameters and nested functions,
647 * solely to diagnose name collisions.
649 localsymtab = new DsymbolTable();
651 // Establish function scope
652 ScopeDsymbol *ss = new ScopeDsymbol();
653 ss->parent = sc->scopesym;
654 Scope *sc2 = sc->push(ss);
655 sc2->func = this;
656 sc2->parent = this;
657 sc2->callSuper = 0;
658 sc2->sbreak = NULL;
659 sc2->scontinue = NULL;
660 sc2->sw = NULL;
661 sc2->fes = fes;
662 sc2->linkage = LINKd;
663 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCfinal);
664 sc2->attributes = NULL;
665 sc2->protection = PROTpublic;
666 sc2->explicitProtection = 0;
667 sc2->structalign = 8;
668 sc2->incontract = 0;
669 sc2->tf = NULL;
670 sc2->noctor = 0;
672 // Declare 'this'
673 ad = isThis();
674 if (ad)
675 { VarDeclaration *v;
677 if (isFuncLiteralDeclaration() && isNested())
679 error("literals cannot be class members");
680 return;
682 else
684 assert(!isNested()); // can't be both member and nested
685 assert(ad->handle);
686 v = new ThisDeclaration(ad->handle);
687 v->storage_class |= STCparameter | STCin;
688 v->semantic(sc2);
689 if (!sc2->insert(v))
690 assert(0);
691 v->parent = this;
692 vthis = v;
695 else if (isNested())
697 VarDeclaration *v;
699 v = new ThisDeclaration(Type::tvoid->pointerTo());
700 v->storage_class |= STCparameter | STCin;
701 v->semantic(sc2);
702 if (!sc2->insert(v))
703 assert(0);
704 v->parent = this;
705 vthis = v;
708 // Declare hidden variable _arguments[] and _argptr
709 if (f->varargs == 1)
710 { Type *t;
712 if (f->linkage == LINKd)
713 { // Declare _arguments[]
714 #if BREAKABI
715 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
716 v_arguments->storage_class = STCparameter | STCin;
717 v_arguments->semantic(sc2);
718 sc2->insert(v_arguments);
719 v_arguments->parent = this;
721 t = Type::typeinfo->type->arrayOf();
722 _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
723 _arguments->skipnullcheck = TRUE;
724 _arguments->semantic(sc2);
725 sc2->insert(_arguments);
726 _arguments->parent = this;
727 #else
728 t = Type::typeinfo->type->arrayOf();
729 v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
730 v_arguments->storage_class = STCparameter | STCin;
731 v_arguments->semantic(sc2);
732 sc2->insert(v_arguments);
733 v_arguments->parent = this;
734 #endif
736 if (f->linkage == LINKd || (parameters && parameters->dim))
737 { // Declare _argptr
738 #if IN_GCC
739 t = d_gcc_builtin_va_list_d_type;
740 #else
741 t = Type::tvoid->pointerTo();
742 #endif
743 argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
744 argptr->skipnullcheck = TRUE;
745 argptr->semantic(sc2);
746 sc2->insert(argptr);
747 argptr->parent = this;
751 // Propagate storage class from tuple parameters to their element-parameters.
752 if (f->parameters)
754 for (size_t i = 0; i < f->parameters->dim; i++)
755 { Argument *arg = (Argument *)f->parameters->data[i];
757 if (arg->type->ty == Ttuple)
758 { TypeTuple *t = (TypeTuple *)arg->type;
759 size_t dim = Argument::dim(t->arguments);
760 for (size_t j = 0; j < dim; j++)
761 { Argument *narg = Argument::getNth(t->arguments, j);
762 narg->storageClass = arg->storageClass;
768 // Declare all the function parameters as variables
769 if (nparams)
770 { /* parameters[] has all the tuples removed, as the back end
771 * doesn't know about tuples
773 parameters = new Dsymbols();
774 parameters->reserve(nparams);
775 for (size_t i = 0; i < nparams; i++)
777 Argument *arg = Argument::getNth(f->parameters, i);
778 Identifier *id = arg->ident;
779 if (!id)
781 /* Generate identifier for un-named parameter,
782 * because we need it later on.
784 OutBuffer buf;
785 buf.printf("_param_%"PRIuSIZE, i);
786 char *name = (char *)buf.extractData();
787 id = new Identifier(name, TOKidentifier);
788 arg->ident = id;
790 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
791 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
792 v->storage_class |= STCparameter;
793 if (f->varargs == 2 && i + 1 == nparams)
794 v->storage_class |= STCvariadic;
795 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy);
796 if (v->storage_class & STClazy)
797 v->storage_class |= STCin;
798 v->semantic(sc2);
799 if (!sc2->insert(v))
800 error("parameter %s.%s is already defined", toChars(), v->toChars());
801 else
802 parameters->push(v);
803 localsymtab->insert(v);
804 v->parent = this;
808 // Declare the tuple symbols and put them in the symbol table,
809 // but not in parameters[].
810 if (f->parameters)
812 for (size_t i = 0; i < f->parameters->dim; i++)
813 { Argument *arg = (Argument *)f->parameters->data[i];
815 if (!arg->ident)
816 continue; // never used, so ignore
817 if (arg->type->ty == Ttuple)
818 { TypeTuple *t = (TypeTuple *)arg->type;
819 size_t dim = Argument::dim(t->arguments);
820 Objects *exps = new Objects();
821 exps->setDim(dim);
822 for (size_t j = 0; j < dim; j++)
823 { Argument *narg = Argument::getNth(t->arguments, j);
824 assert(narg->ident);
825 VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
826 assert(v);
827 Expression *e = new VarExp(0, v);
828 exps->data[j] = (void *)e;
830 assert(arg->ident);
831 TupleDeclaration *v = new TupleDeclaration(0, arg->ident, exps);
832 //printf("declaring tuple %s\n", v->toChars());
833 v->isexp = 1;
834 if (!sc2->insert(v))
835 error("parameter %s.%s is already defined", toChars(), v->toChars());
836 localsymtab->insert(v);
837 v->parent = this;
842 /* Do the semantic analysis on the [in] preconditions and
843 * [out] postconditions.
845 sc2->incontract++;
847 if (frequire)
848 { /* frequire is composed of the [in] contracts
850 // BUG: need to error if accessing out parameters
851 // BUG: need to treat parameters as const
852 // BUG: need to disallow returns and throws
853 // BUG: verify that all in and ref parameters are read
854 frequire = frequire->semantic(sc2);
855 labtab = NULL; // so body can't refer to labels
858 if (fensure || addPostInvariant())
859 { /* fensure is composed of the [out] contracts
861 ScopeDsymbol *sym = new ScopeDsymbol();
862 sym->parent = sc2->scopesym;
863 sc2 = sc2->push(sym);
865 assert(type->nextOf());
866 if (type->nextOf()->ty == Tvoid)
868 if (outId)
869 error("void functions have no result");
871 else
873 if (!outId)
874 outId = Id::result; // provide a default
877 if (outId)
878 { // Declare result variable
879 VarDeclaration *v;
880 Loc loc = this->loc;
882 if (fensure)
883 loc = fensure->loc;
885 v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
886 v->noauto = 1;
887 v->skipnullcheck = 1;
888 sc2->incontract--;
889 v->semantic(sc2);
890 sc2->incontract++;
891 if (!sc2->insert(v))
892 error("out result %s is already defined", v->toChars());
893 v->parent = this;
894 vresult = v;
896 // vresult gets initialized with the function return value
897 // in ReturnStatement::semantic()
900 // BUG: need to treat parameters as const
901 // BUG: need to disallow returns and throws
902 if (fensure)
903 { fensure = fensure->semantic(sc2);
904 labtab = NULL; // so body can't refer to labels
907 if (!global.params.useOut)
908 { fensure = NULL; // discard
909 vresult = NULL;
912 // Postcondition invariant
913 if (addPostInvariant())
915 Expression *e = NULL;
916 if (isCtorDeclaration())
918 // Call invariant directly only if it exists
919 InvariantDeclaration *inv = ad->inv;
920 ClassDeclaration *cd = ad->isClassDeclaration();
922 while (!inv && cd)
924 cd = cd->baseClass;
925 if (!cd)
926 break;
927 inv = cd->inv;
929 if (inv)
931 e = new DsymbolExp(0, inv);
932 e = new CallExp(0, e);
933 e = e->semantic(sc2);
936 else
937 { // Call invariant virtually
938 ThisExp *v = new ThisExp(0);
939 v->type = vthis->type;
940 e = new AssertExp(0, v);
942 if (e)
944 ExpStatement *s = new ExpStatement(0, e);
945 if (fensure)
946 fensure = new CompoundStatement(0, s, fensure);
947 else
948 fensure = s;
952 if (fensure)
953 { returnLabel = new LabelDsymbol(Id::returnLabel);
954 LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
955 ls->isReturnLabel = 1;
956 returnLabel->statement = ls;
958 sc2 = sc2->pop();
961 sc2->incontract--;
963 if (fbody)
964 { ClassDeclaration *cd = isClassMember();
966 /* If this is a class constructor
968 if (isCtorDeclaration() && cd)
970 for (int i = 0; i < cd->fields.dim; i++)
971 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
973 v->ctorinit = 0;
977 if (inferRetType || f->retStyle() != RETstack)
978 nrvo_can = 0;
980 fbody = fbody->semantic(sc2);
982 if (inferRetType)
983 { // If no return type inferred yet, then infer a void
984 if (!type->nextOf())
986 ((TypeFunction *)type)->next = Type::tvoid;
987 type = type->semantic(loc, sc);
989 f = (TypeFunction *)type;
992 int offend = fbody ? fbody->fallOffEnd() : TRUE;
994 if (isStaticCtorDeclaration())
995 { /* It's a static constructor. Ensure that all
996 * ctor consts were initialized.
999 Dsymbol *p = toParent();
1000 ScopeDsymbol *ad = p->isScopeDsymbol();
1001 if (!ad)
1003 error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
1005 else
1007 for (int i = 0; i < ad->members->dim; i++)
1008 { Dsymbol *s = (Dsymbol *)ad->members->data[i];
1010 s->checkCtorConstInit();
1015 if (isCtorDeclaration() && cd)
1017 //printf("callSuper = x%x\n", sc2->callSuper);
1019 // Verify that all the ctorinit fields got initialized
1020 // Also check that non-null members got set
1021 if (!(sc2->callSuper & CSXthis_ctor))
1023 for (int i = 0; i < cd->fields.dim; i++)
1024 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
1026 if (v->ctorinit == 0)
1028 if (v->isCtorinit())
1029 error("missing initializer for const field %s", v->toChars());
1030 else if (v->type->ty == Tclass || v->type->ty == Tpointer)
1031 error("missing initializer for non-null field %s", v->toChars());
1036 if (!(sc2->callSuper & CSXany_ctor) &&
1037 cd->baseClass && cd->baseClass->ctor)
1039 sc2->callSuper = 0;
1041 // Insert implicit super() at start of fbody
1042 Expression *e1 = new SuperExp(0);
1043 Expression *e = new CallExp(0, e1);
1045 unsigned errors = global.errors;
1046 global.gag++;
1047 e = e->semantic(sc2);
1048 global.gag--;
1049 if (errors != global.errors)
1050 error("no match for implicit super() call in constructor");
1052 Statement *s = new ExpStatement(0, e);
1053 fbody = new CompoundStatement(0, s, fbody);
1056 else if (fes)
1057 { // For foreach(){} body, append a return 0;
1058 Expression *e = new IntegerExp(0);
1059 Statement *s = new ReturnStatement(0, e);
1060 fbody = new CompoundStatement(0, fbody, s);
1061 assert(!returnLabel);
1063 else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1064 error("expected to return a value of type %s", type->nextOf()->toChars());
1065 else if (!inlineAsm)
1067 if (type->nextOf()->ty == Tvoid)
1069 if (offend && isMain())
1070 { // Add a return 0; statement
1071 Statement *s = new ReturnStatement(0, new IntegerExp(0));
1072 fbody = new CompoundStatement(0, fbody, s);
1075 else
1077 if (offend)
1078 { Expression *e;
1080 if (global.params.warnings)
1081 { fprintf(stdmsg, "warning - ");
1082 error("no return at end of function");
1085 if (global.params.useAssert &&
1086 !global.params.useInline)
1087 { /* Add an assert(0, msg); where the missing return
1088 * should be.
1090 e = new AssertExp(
1091 endloc,
1092 new IntegerExp(0),
1093 new StringExp(loc, "missing return expression")
1096 else
1097 e = new HaltExp(endloc);
1098 e = new CommaExp(0, e, type->nextOf()->defaultInit());
1099 e = e->semantic(sc2);
1100 Statement *s = new ExpStatement(0, e);
1101 fbody = new CompoundStatement(0, fbody, s);
1108 Statements *a = new Statements();
1110 // Merge in initialization of 'out' parameters
1111 if (parameters)
1112 { for (size_t i = 0; i < parameters->dim; i++)
1114 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1115 if (v->storage_class & STCout)
1117 assert(v->init);
1118 ExpInitializer *ie = v->init->isExpInitializer();
1119 assert(ie);
1120 a->push(new ExpStatement(0, ie->exp));
1125 if (argptr)
1126 { // Initialize _argptr to point past non-variadic arg
1127 #if IN_GCC
1128 // Handled in FuncDeclaration::toObjFile
1129 v_argptr = argptr;
1130 v_argptr->init = new VoidInitializer(loc);
1131 #else
1132 Expression *e1;
1133 Expression *e;
1134 Type *t = argptr->type;
1135 VarDeclaration *p;
1136 unsigned offset;
1138 e1 = new VarExp(0, argptr);
1139 if (parameters && parameters->dim)
1140 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1141 else
1142 p = v_arguments; // last parameter is _arguments[]
1143 offset = p->type->size();
1144 offset = (offset + 3) & ~3; // assume stack aligns on 4
1145 e = new SymOffExp(0, p, offset);
1146 e = new AssignExp(0, e1, e);
1147 e->type = t;
1148 a->push(new ExpStatement(0, e));
1149 #endif
1152 if (_arguments)
1154 #if IN_GCC
1155 v_arguments_var = _arguments;
1156 v_arguments_var->init = new VoidInitializer(loc);
1157 #endif
1158 /* Advance to elements[] member of TypeInfo_Tuple with:
1159 * _arguments = v_arguments.elements;
1161 Expression *e = new VarExp(0, v_arguments);
1162 e = new DotIdExp(0, e, Id::elements);
1163 Expression *e1 = new VarExp(0, _arguments);
1164 e = new AssignExp(0, e1, e);
1165 e = e->semantic(sc);
1166 a->push(new ExpStatement(0, e));
1169 // Merge contracts together with body into one compound statement
1171 #ifdef _DH
1172 if (frequire && global.params.useIn)
1173 { frequire->incontract = 1;
1174 a->push(frequire);
1176 #else
1177 if (frequire && global.params.useIn)
1178 a->push(frequire);
1179 #endif
1181 // Precondition invariant
1182 if (addPreInvariant())
1184 Expression *e = NULL;
1185 if (isDtorDeclaration())
1187 // Call invariant directly only if it exists
1188 InvariantDeclaration *inv = ad->inv;
1189 ClassDeclaration *cd = ad->isClassDeclaration();
1191 while (!inv && cd)
1193 cd = cd->baseClass;
1194 if (!cd)
1195 break;
1196 inv = cd->inv;
1198 if (inv)
1200 e = new DsymbolExp(0, inv);
1201 e = new CallExp(0, e);
1202 e = e->semantic(sc2);
1205 else
1206 { // Call invariant virtually
1207 ThisExp *v = new ThisExp(0);
1208 v->type = vthis->type;
1209 Expression *se = new StringExp(0, "null this");
1210 se = se->semantic(sc);
1211 se->type = Type::tchar->arrayOf();
1212 e = new AssertExp(loc, v, se);
1214 if (e)
1216 ExpStatement *s = new ExpStatement(0, e);
1217 a->push(s);
1221 if (fbody)
1222 a->push(fbody);
1224 if (fensure)
1226 a->push(returnLabel->statement);
1228 if (type->nextOf()->ty != Tvoid)
1230 // Create: return vresult;
1231 assert(vresult);
1232 Expression *e = new VarExp(0, vresult);
1233 if (tintro)
1234 { e = e->implicitCastTo(sc, tintro->nextOf());
1235 e = e->semantic(sc);
1237 ReturnStatement *s = new ReturnStatement(0, e);
1238 a->push(s);
1242 fbody = new CompoundStatement(0, a);
1245 sc2->callSuper = 0;
1246 sc2->pop();
1248 semanticRun = 2;
1251 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1253 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1255 type->toCBuffer(buf, ident, hgs);
1256 bodyToCBuffer(buf, hgs);
1260 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1262 if (fbody &&
1263 (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1265 { buf->writenl();
1267 // in{}
1268 if (frequire)
1269 { buf->writestring("in");
1270 buf->writenl();
1271 frequire->toCBuffer(buf, hgs);
1274 // out{}
1275 if (fensure)
1276 { buf->writestring("out");
1277 if (outId)
1278 { buf->writebyte('(');
1279 buf->writestring(outId->toChars());
1280 buf->writebyte(')');
1282 buf->writenl();
1283 fensure->toCBuffer(buf, hgs);
1286 if (frequire || fensure)
1287 { buf->writestring("body");
1288 buf->writenl();
1291 buf->writebyte('{');
1292 buf->writenl();
1293 fbody->toCBuffer(buf, hgs);
1294 buf->writebyte('}');
1295 buf->writenl();
1297 else
1298 { buf->writeByte(';');
1299 buf->writenl();
1303 /****************************************************
1304 * Determine if 'this' overrides fd.
1305 * Return !=0 if it does.
1308 int FuncDeclaration::overrides(FuncDeclaration *fd)
1309 { int result = 0;
1311 if (fd->ident == ident)
1313 int cov = type->covariant(fd->type);
1314 if (cov)
1315 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1316 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1318 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1319 result = 1;
1322 return result;
1325 /*************************************************
1326 * Find index of function in vtbl[0..dim] that
1327 * this function overrides.
1328 * Returns:
1329 * -1 didn't find one
1330 * -2 can't determine because of forward references
1333 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
1335 for (int vi = 0; vi < dim; vi++)
1337 FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
1338 if (fdv && fdv->ident == ident)
1340 int cov = type->covariant(fdv->type);
1341 //printf("\tbaseclass cov = %d\n", cov);
1342 switch (cov)
1344 case 0: // types are distinct
1345 break;
1347 case 1:
1348 return vi;
1350 case 2:
1351 //type->print();
1352 //fdv->type->print();
1353 //printf("%s %s\n", type->deco, fdv->type->deco);
1354 error("of type %s overrides but is not covariant with %s of type %s",
1355 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
1356 break;
1358 case 3:
1359 return -2; // forward references
1361 default:
1362 assert(0);
1366 return -1;
1369 /****************************************************
1370 * Overload this FuncDeclaration with the new one f.
1371 * Return !=0 if successful; i.e. no conflict.
1374 int FuncDeclaration::overloadInsert(Dsymbol *s)
1376 FuncDeclaration *f;
1377 AliasDeclaration *a;
1379 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1380 a = s->isAliasDeclaration();
1381 if (a)
1383 if (overnext)
1384 return overnext->overloadInsert(a);
1385 if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1387 //printf("\ta = '%s'\n", a->type->toChars());
1388 return FALSE;
1390 overnext = a;
1391 //printf("\ttrue: no conflict\n");
1392 return TRUE;
1394 f = s->isFuncDeclaration();
1395 if (!f)
1396 return FALSE;
1398 if (type && f->type && // can be NULL for overloaded constructors
1399 f->type->covariant(type) &&
1400 !isFuncAliasDeclaration())
1402 //printf("\tfalse: conflict %s\n", kind());
1403 return FALSE;
1406 if (overnext)
1407 return overnext->overloadInsert(f);
1408 overnext = f;
1409 //printf("\ttrue: no conflict\n");
1410 return TRUE;
1413 /********************************************
1414 * Find function in overload list that exactly matches t.
1417 /***************************************************
1418 * Visit each overloaded function in turn, and call
1419 * (*fp)(param, f) on it.
1420 * Exit when no more, or (*fp)(param, f) returns 1.
1421 * Returns:
1422 * 0 continue
1423 * 1 done
1426 int overloadApply(FuncDeclaration *fstart,
1427 int (*fp)(void *, FuncDeclaration *),
1428 void *param)
1430 FuncDeclaration *f;
1431 Declaration *d;
1432 Declaration *next;
1434 for (d = fstart; d; d = next)
1435 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1437 if (fa)
1439 if (overloadApply(fa->funcalias, fp, param))
1440 return 1;
1441 next = fa->overnext;
1443 else
1445 AliasDeclaration *a = d->isAliasDeclaration();
1447 if (a)
1449 Dsymbol *s = a->toAlias();
1450 next = s->isDeclaration();
1451 if (next == a)
1452 break;
1453 if (next == fstart)
1454 break;
1456 else
1458 f = d->isFuncDeclaration();
1459 if (!f)
1460 { d->error("is aliased to a function");
1461 break; // BUG: should print error message?
1463 if ((*fp)(param, f))
1464 return 1;
1466 next = f->overnext;
1470 return 0;
1473 /********************************************
1474 * Find function in overload list that exactly matches t.
1477 struct Param1
1479 Type *t; // type to match
1480 FuncDeclaration *f; // return value
1483 int fp1(void *param, FuncDeclaration *f)
1484 { Param1 *p = (Param1 *)param;
1485 Type *t = p->t;
1487 if (t->equals(f->type))
1488 { p->f = f;
1489 return 1;
1492 #if V2
1493 /* Allow covariant matches, if it's just a const conversion
1494 * of the return type
1496 if (t->ty == Tfunction)
1497 { TypeFunction *tf = (TypeFunction *)f->type;
1498 if (tf->covariant(t) == 1 &&
1499 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
1501 p->f = f;
1502 return 1;
1505 #endif
1506 return 0;
1509 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1511 Param1 p;
1512 p.t = t;
1513 p.f = NULL;
1514 overloadApply(this, &fp1, &p);
1515 return p.f;
1518 #if 0
1519 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1521 FuncDeclaration *f;
1522 Declaration *d;
1523 Declaration *next;
1525 for (d = this; d; d = next)
1526 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1528 if (fa)
1530 FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t);
1531 if (f2)
1532 return f2;
1533 next = fa->overnext;
1535 else
1537 AliasDeclaration *a = d->isAliasDeclaration();
1539 if (a)
1541 Dsymbol *s = a->toAlias();
1542 next = s->isDeclaration();
1543 if (next == a)
1544 break;
1546 else
1548 f = d->isFuncDeclaration();
1549 if (!f)
1550 break; // BUG: should print error message?
1551 if (t->equals(d->type))
1552 return f;
1553 next = f->overnext;
1557 return NULL;
1559 #endif
1561 /********************************************
1562 * Decide which function matches the arguments best.
1565 struct Param2
1567 Match *m;
1568 Expressions *arguments;
1571 int fp2(void *param, FuncDeclaration *f)
1572 { Param2 *p = (Param2 *)param;
1573 Match *m = p->m;
1574 Expressions *arguments = p->arguments;
1575 MATCH match;
1577 if (f != m->lastf) // skip duplicates
1579 TypeFunction *tf;
1581 m->anyf = f;
1582 tf = (TypeFunction *)f->type;
1583 match = (MATCH) tf->callMatch(arguments);
1584 //printf("match = %d\n", match);
1585 if (match != MATCHnomatch)
1587 if (match > m->last)
1588 goto LfIsBetter;
1590 if (match < m->last)
1591 goto LlastIsBetter;
1593 /* See if one of the matches overrides the other.
1595 if (m->lastf->overrides(f))
1596 goto LlastIsBetter;
1597 else if (f->overrides(m->lastf))
1598 goto LfIsBetter;
1600 Lambiguous:
1601 m->nextf = f;
1602 m->count++;
1603 return 0;
1605 LfIsBetter:
1606 m->last = match;
1607 m->lastf = f;
1608 m->count = 1;
1609 return 0;
1611 LlastIsBetter:
1612 return 0;
1615 return 0;
1619 void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
1621 Param2 p;
1622 p.m = m;
1623 p.arguments = arguments;
1624 overloadApply(fstart, &fp2, &p);
1627 #if 0
1628 // Recursive helper function
1630 void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
1632 MATCH match;
1633 Declaration *d;
1634 Declaration *next;
1636 for (d = fstart; d; d = next)
1638 FuncDeclaration *f;
1639 FuncAliasDeclaration *fa;
1640 AliasDeclaration *a;
1642 fa = d->isFuncAliasDeclaration();
1643 if (fa)
1645 overloadResolveX(m, fa->funcalias, arguments);
1646 next = fa->overnext;
1648 else if ((f = d->isFuncDeclaration()) != NULL)
1650 next = f->overnext;
1651 if (f == m->lastf)
1652 continue; // skip duplicates
1653 else
1655 TypeFunction *tf;
1657 m->anyf = f;
1658 tf = (TypeFunction *)f->type;
1659 match = (MATCH) tf->callMatch(arguments);
1660 //printf("match = %d\n", match);
1661 if (match != MATCHnomatch)
1663 if (match > m->last)
1664 goto LfIsBetter;
1666 if (match < m->last)
1667 goto LlastIsBetter;
1669 /* See if one of the matches overrides the other.
1671 if (m->lastf->overrides(f))
1672 goto LlastIsBetter;
1673 else if (f->overrides(m->lastf))
1674 goto LfIsBetter;
1676 Lambiguous:
1677 m->nextf = f;
1678 m->count++;
1679 continue;
1681 LfIsBetter:
1682 m->last = match;
1683 m->lastf = f;
1684 m->count = 1;
1685 continue;
1687 LlastIsBetter:
1688 continue;
1692 else if ((a = d->isAliasDeclaration()) != NULL)
1694 Dsymbol *s = a->toAlias();
1695 next = s->isDeclaration();
1696 if (next == a)
1697 break;
1698 if (next == fstart)
1699 break;
1701 else
1702 { d->error("is aliased to a function");
1703 break;
1707 #endif
1709 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expressions *arguments)
1711 TypeFunction *tf;
1712 Match m;
1714 #if 0
1715 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1716 if (arguments)
1717 { int i;
1719 for (i = 0; i < arguments->dim; i++)
1720 { Expression *arg;
1722 arg = (Expression *)arguments->data[i];
1723 assert(arg->type);
1724 printf("\t%s: ", arg->toChars());
1725 arg->type->print();
1728 #endif
1730 memset(&m, 0, sizeof(m));
1731 m.last = MATCHnomatch;
1732 overloadResolveX(&m, this, arguments);
1734 if (m.count == 1) // exactly one match
1736 return m.lastf;
1738 else
1740 OutBuffer buf;
1742 if (arguments)
1744 HdrGenState hgs;
1746 argExpTypesToCBuffer(&buf, arguments, &hgs);
1749 if (m.last == MATCHnomatch)
1751 tf = (TypeFunction *)type;
1753 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1754 error(loc, "%s does not match parameter types (%s)",
1755 Argument::argsTypesToChars(tf->parameters, tf->varargs),
1756 buf.toChars());
1757 return m.anyf; // as long as it's not a FuncAliasDeclaration
1759 else
1761 #if 1
1762 TypeFunction *t1 = (TypeFunction *)m.lastf->type;
1763 TypeFunction *t2 = (TypeFunction *)m.nextf->type;
1765 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1766 buf.toChars(),
1767 m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
1768 m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
1769 #else
1770 error(loc, "overloads %s and %s both match argument list for %s",
1771 m.lastf->type->toChars(),
1772 m.nextf->type->toChars(),
1773 m.lastf->toChars());
1774 #endif
1775 return m.lastf;
1780 /********************************
1781 * Labels are in a separate scope, one per function.
1784 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
1785 { Dsymbol *s;
1787 if (!labtab)
1788 labtab = new DsymbolTable(); // guess we need one
1790 s = labtab->lookup(ident);
1791 if (!s)
1793 s = new LabelDsymbol(ident);
1794 labtab->insert(s);
1796 return (LabelDsymbol *)s;
1798 /****************************************
1799 * If non-static member function that has a 'this' pointer,
1800 * return the aggregate it is a member of.
1801 * Otherwise, return NULL.
1804 AggregateDeclaration *FuncDeclaration::isThis()
1805 { AggregateDeclaration *ad;
1807 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1808 ad = NULL;
1809 if ((storage_class & STCstatic) == 0)
1811 ad = isMember2();
1813 //printf("-FuncDeclaration::isThis() %p\n", ad);
1814 return ad;
1817 AggregateDeclaration *FuncDeclaration::isMember2()
1818 { AggregateDeclaration *ad;
1820 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1821 ad = NULL;
1822 for (Dsymbol *s = this; s; s = s->parent)
1824 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1825 ad = s->isMember();
1826 if (ad)
1827 { //printf("test4\n");
1828 break;
1830 if (!s->parent ||
1831 (!s->parent->isTemplateInstance()))
1832 { //printf("test5\n");
1833 break;
1836 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1837 return ad;
1840 /*****************************************
1841 * Determine lexical level difference from 'this' to nested function 'fd'.
1842 * Error if this cannot call fd.
1843 * Returns:
1844 * 0 same level
1845 * -1 increase nesting by 1 (fd is nested within 'this')
1846 * >0 decrease nesting by number
1849 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
1850 { int level;
1851 Dsymbol *s;
1852 Dsymbol *fdparent;
1854 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1855 fdparent = fd->toParent2();
1856 if (fdparent == this)
1857 return -1;
1858 s = this;
1859 level = 0;
1860 while (fd != s && fdparent != s->toParent2())
1862 //printf("\ts = '%s'\n", s->toChars());
1863 FuncDeclaration *thisfd = s->isFuncDeclaration();
1864 if (thisfd)
1865 { if (!thisfd->isNested() && !thisfd->vthis)
1866 goto Lerr;
1868 else
1870 ClassDeclaration *thiscd = s->isClassDeclaration();
1871 if (thiscd)
1872 { if (!thiscd->isNested())
1873 goto Lerr;
1875 else
1876 goto Lerr;
1879 s = s->toParent2();
1880 assert(s);
1881 level++;
1883 return level;
1885 Lerr:
1886 error(loc, "cannot access frame of function %s", fd->toChars());
1887 return 1;
1890 void FuncDeclaration::appendExp(Expression *e)
1891 { Statement *s;
1893 s = new ExpStatement(0, e);
1894 appendState(s);
1897 void FuncDeclaration::appendState(Statement *s)
1898 { CompoundStatement *cs;
1900 if (!fbody)
1901 { Statements *a;
1903 a = new Statements();
1904 fbody = new CompoundStatement(0, a);
1906 cs = fbody->isCompoundStatement();
1907 cs->statements->push(s);
1911 int FuncDeclaration::isMain()
1913 return ident == Id::main &&
1914 linkage != LINKc && !isMember() && !isNested();
1917 int FuncDeclaration::isWinMain()
1919 return ident == Id::WinMain &&
1920 linkage != LINKc && !isMember();
1923 int FuncDeclaration::isDllMain()
1925 return ident == Id::DllMain &&
1926 linkage != LINKc && !isMember();
1929 int FuncDeclaration::isExport()
1931 return protection == PROTexport;
1934 int FuncDeclaration::isImportedSymbol()
1936 //printf("isImportedSymbol()\n");
1937 //printf("protection = %d\n", protection);
1938 return (protection == PROTexport) && !fbody;
1941 // Determine if function goes into virtual function pointer table
1943 int FuncDeclaration::isVirtual()
1945 #if 0
1946 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1947 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
1948 printf("result is %d\n",
1949 isMember() &&
1950 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1951 toParent()->isClassDeclaration());
1952 #endif
1953 return isMember() &&
1954 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1955 toParent()->isClassDeclaration();
1958 int FuncDeclaration::isAbstract()
1960 return storage_class & STCabstract;
1963 int FuncDeclaration::isCodeseg()
1965 return TRUE; // functions are always in the code segment
1968 // Determine if function needs
1969 // a static frame pointer to its lexically enclosing function
1971 int FuncDeclaration::isNested()
1973 //if (!toParent())
1974 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
1975 //printf("\ttoParent() = '%s'\n", toParent()->toChars());
1976 return ((storage_class & STCstatic) == 0) &&
1977 (toParent2()->isFuncDeclaration() != NULL);
1980 int FuncDeclaration::needThis()
1982 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
1983 int i = isThis() != NULL;
1984 //printf("\t%d\n", i);
1985 if (!i && isFuncAliasDeclaration())
1986 i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
1987 return i;
1990 int FuncDeclaration::addPreInvariant()
1992 AggregateDeclaration *ad = isThis();
1993 return (ad &&
1994 //ad->isClassDeclaration() &&
1995 global.params.useInvariants &&
1996 (protection == PROTpublic || protection == PROTexport) &&
1997 !naked);
2000 int FuncDeclaration::addPostInvariant()
2002 AggregateDeclaration *ad = isThis();
2003 return (ad &&
2004 ad->inv &&
2005 //ad->isClassDeclaration() &&
2006 global.params.useInvariants &&
2007 (protection == PROTpublic || protection == PROTexport) &&
2008 !naked);
2011 /**********************************
2012 * Generate a FuncDeclaration for a runtime library function.
2015 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name,
2016 Type *t1, Type *t2, Type *t3)
2018 return genCfunc(treturn, Lexer::idPool(name), t1, t2, t3);
2021 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id,
2022 Type *t1, Type *t2, Type *t3)
2024 FuncDeclaration *fd;
2025 TypeFunction *tf;
2026 Dsymbol *s;
2027 static DsymbolTable *st = NULL;
2029 //printf("genCfunc(name = '%s')\n", id->toChars());
2030 //printf("treturn\n\t"); treturn->print();
2032 // See if already in table
2033 if (!st)
2034 st = new DsymbolTable();
2035 s = st->lookup(id);
2036 if (s)
2038 fd = s->isFuncDeclaration();
2039 assert(fd);
2040 assert(fd->type->nextOf()->equals(treturn));
2042 else
2044 Arguments * args = 0;
2045 if (t1) {
2046 args = new Arguments;
2047 args->push(new Argument(STCin,t1,0,0));
2048 if (t2)
2050 args->push(new Argument(STCin,t2,0,0));
2051 if (t3)
2052 args->push(new Argument(STCin,t3,0,0));
2056 tf = new TypeFunction(args, treturn, 0, LINKc);
2057 fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2058 fd->protection = PROTpublic;
2059 fd->linkage = LINKc;
2061 st->insert(fd);
2063 return fd;
2066 char *FuncDeclaration::kind()
2068 return "function";
2070 /*******************************
2071 * Look at all the variables in this function that are referenced
2072 * by nested functions, and determine if a closure needs to be
2073 * created for them.
2076 #if V2
2077 int FuncDeclaration::needsClosure()
2079 /* Need a closure for all the closureVars[] if any of the
2080 * closureVars[] are accessed by a
2081 * function that escapes the scope of this function.
2082 * We take the conservative approach and decide that any function that:
2083 * 1) is a virtual function
2084 * 2) has its address taken
2085 * 3) has a parent that escapes
2086 * escapes.
2089 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2090 for (int i = 0; i < closureVars.dim; i++)
2091 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
2092 assert(v->isVarDeclaration());
2093 //printf("\tv = %s\n", v->toChars());
2095 for (int j = 0; j < v->nestedrefs.dim; j++)
2096 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
2097 assert(f != this);
2099 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2100 if (f->isVirtual() || f->tookAddressOf)
2101 goto Lyes; // assume f escapes this function's scope
2103 // Look to see if any parents of f that are below this escape
2104 for (Dsymbol *s = f->parent; s != this; s = s->parent)
2106 f = s->isFuncDeclaration();
2107 if (f && (f->isVirtual() || f->tookAddressOf))
2108 goto Lyes;
2112 return 0;
2114 Lyes:
2115 //printf("\tneeds closure\n");
2116 return 1;
2118 #endif
2120 /****************************** FuncAliasDeclaration ************************/
2122 // Used as a way to import a set of functions from another scope into this one.
2124 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2125 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2126 (enum STC)funcalias->storage_class, funcalias->type)
2128 assert(funcalias != this);
2129 this->funcalias = funcalias;
2132 char *FuncAliasDeclaration::kind()
2134 return "function alias";
2138 /****************************** FuncLiteralDeclaration ************************/
2140 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2141 enum TOK tok, ForeachStatement *fes)
2142 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2144 char *id;
2146 if (fes)
2147 id = "__foreachbody";
2148 else if (tok == TOKdelegate)
2149 id = "__dgliteral";
2150 else
2151 id = "__funcliteral";
2152 this->ident = Identifier::generateId(id);
2153 this->tok = tok;
2154 this->fes = fes;
2155 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2158 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2160 FuncLiteralDeclaration *f;
2162 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2163 if (s)
2164 f = (FuncLiteralDeclaration *)s;
2165 else
2166 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2167 FuncDeclaration::syntaxCopy(f);
2168 return f;
2171 int FuncLiteralDeclaration::isNested()
2173 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2174 return (tok == TOKdelegate);
2177 char *FuncLiteralDeclaration::kind()
2179 // GCC requires the (char*) casts
2180 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
2183 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2185 static Identifier *idfunc;
2186 static Identifier *iddel;
2188 if (!idfunc)
2189 idfunc = new Identifier("function", 0);
2190 if (!iddel)
2191 iddel = new Identifier("delegate", 0);
2193 type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
2194 bodyToCBuffer(buf, hgs);
2198 /********************************* CtorDeclaration ****************************/
2200 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2201 : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
2203 this->arguments = arguments;
2204 this->varargs = varargs;
2205 //printf("CtorDeclaration() %s\n", toChars());
2208 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2210 CtorDeclaration *f;
2212 f = new CtorDeclaration(loc, endloc, NULL, varargs);
2214 f->outId = outId;
2215 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2216 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
2217 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
2218 assert(!fthrows); // deprecated
2220 f->arguments = Argument::arraySyntaxCopy(arguments);
2221 return f;
2225 void CtorDeclaration::semantic(Scope *sc)
2227 ClassDeclaration *cd;
2228 Type *tret;
2230 //printf("CtorDeclaration::semantic()\n");
2231 if (type)
2232 return;
2234 sc = sc->push();
2235 sc->stc &= ~STCstatic; // not a static constructor
2237 parent = sc->parent;
2238 Dsymbol *parent = toParent();
2239 cd = parent->isClassDeclaration();
2240 if (!cd)
2242 error("constructors are only for class definitions");
2243 tret = Type::tvoid;
2245 else
2247 tret = cd->type; //->referenceTo();
2249 for (int i = 0; i < cd->fields.dim; i++)
2251 VarDeclaration *vd = (VarDeclaration *) cd->fields.data[i];
2252 if (vd->isIn())
2254 if (!arguments)
2255 arguments = new Arguments();
2256 Argument *a = new Argument(vd->storage_class, vd->type, vd->ident, 0);
2257 // BUG: We don't really want these arguments in scope...
2258 arguments->push(a);
2260 Statement *assign = new ExpStatement(loc, new AssignExp(loc,
2261 new DotIdExp(loc, new ThisExp(loc), a->ident),
2262 new IdentifierExp(loc, a->ident)));
2263 if (fbody)
2264 fbody = new CompoundStatement(loc, assign, fbody);
2265 else
2266 fbody = assign;
2271 type = new TypeFunction(arguments, tret, varargs, LINKd);
2273 sc->flags |= SCOPEctor;
2274 type = type->semantic(loc, sc);
2275 sc->flags &= ~SCOPEctor;
2277 // Append:
2278 // return this;
2279 // to the function body
2280 if (fbody)
2281 { Expression *e;
2282 Statement *s;
2284 e = new ThisExp(0);
2285 s = new ReturnStatement(0, e);
2286 fbody = new CompoundStatement(0, fbody, s);
2289 FuncDeclaration::semantic(sc);
2291 sc->pop();
2293 // See if it's the default constructor
2294 if (cd && varargs == 0 && Argument::dim(arguments) == 0)
2295 cd->defaultCtor = this;
2298 char *CtorDeclaration::kind()
2300 return "constructor";
2303 char *CtorDeclaration::toChars()
2305 return "this";
2308 int CtorDeclaration::isVirtual()
2310 return FALSE;
2313 int CtorDeclaration::addPreInvariant()
2315 return FALSE;
2318 int CtorDeclaration::addPostInvariant()
2320 return (vthis && global.params.useInvariants);
2324 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2326 buf->writestring("this");
2327 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2328 bodyToCBuffer(buf, hgs);
2331 /********************************* DtorDeclaration ****************************/
2333 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
2334 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
2338 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
2339 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2343 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
2345 assert(!s);
2346 DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
2347 return FuncDeclaration::syntaxCopy(dd);
2351 void DtorDeclaration::semantic(Scope *sc)
2353 ClassDeclaration *cd;
2355 parent = sc->parent;
2356 Dsymbol *parent = toParent();
2357 cd = parent->isClassDeclaration();
2358 if (!cd)
2360 error("destructors only are for class definitions");
2362 else
2363 cd->dtors.push(this);
2364 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2366 sc = sc->push();
2367 sc->stc &= ~STCstatic; // not a static destructor
2368 sc->linkage = LINKd;
2370 FuncDeclaration::semantic(sc);
2372 sc->pop();
2375 int DtorDeclaration::overloadInsert(Dsymbol *s)
2377 return FALSE; // cannot overload destructors
2380 int DtorDeclaration::addPreInvariant()
2382 return (vthis && global.params.useInvariants);
2385 int DtorDeclaration::addPostInvariant()
2387 return FALSE;
2390 int DtorDeclaration::isVirtual()
2392 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2393 * but doing so will require recompiling everything.
2395 #if BREAKABI
2396 return FALSE;
2397 #else
2398 return FuncDeclaration::isVirtual();
2399 #endif
2402 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2404 if (hgs->hdrgen)
2405 return;
2406 buf->writestring("~this()");
2407 bodyToCBuffer(buf, hgs);
2410 /********************************* StaticCtorDeclaration ****************************/
2412 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
2413 : FuncDeclaration(loc, endloc,
2414 Identifier::generateId("_staticCtor"), STCstatic, NULL)
2418 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
2420 StaticCtorDeclaration *scd;
2422 assert(!s);
2423 scd = new StaticCtorDeclaration(loc, endloc);
2424 return FuncDeclaration::syntaxCopy(scd);
2428 void StaticCtorDeclaration::semantic(Scope *sc)
2430 //printf("StaticCtorDeclaration::semantic()\n");
2432 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2434 FuncDeclaration::semantic(sc);
2436 // We're going to need ModuleInfo
2437 Module *m = getModule();
2438 if (!m)
2439 m = sc->module;
2440 if (m)
2441 { m->needmoduleinfo = 1;
2442 #ifdef IN_GCC
2443 m->strictlyneedmoduleinfo = 1;
2444 #endif
2448 AggregateDeclaration *StaticCtorDeclaration::isThis()
2450 return NULL;
2453 int StaticCtorDeclaration::isStaticConstructor()
2455 return TRUE;
2458 int StaticCtorDeclaration::isVirtual()
2460 return FALSE;
2463 int StaticCtorDeclaration::addPreInvariant()
2465 return FALSE;
2468 int StaticCtorDeclaration::addPostInvariant()
2470 return FALSE;
2473 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2475 if (hgs->hdrgen)
2476 { buf->writestring("static this();\n");
2477 return;
2479 buf->writestring("static this()");
2480 bodyToCBuffer(buf, hgs);
2483 /********************************* StaticDtorDeclaration ****************************/
2485 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
2486 : FuncDeclaration(loc, endloc,
2487 Identifier::generateId("_staticDtor"), STCstatic, NULL)
2491 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
2493 StaticDtorDeclaration *sdd;
2495 assert(!s);
2496 sdd = new StaticDtorDeclaration(loc, endloc);
2497 return FuncDeclaration::syntaxCopy(sdd);
2501 void StaticDtorDeclaration::semantic(Scope *sc)
2503 ClassDeclaration *cd;
2504 Type *tret;
2506 cd = sc->scopesym->isClassDeclaration();
2507 if (!cd)
2510 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2512 FuncDeclaration::semantic(sc);
2514 // We're going to need ModuleInfo
2515 Module *m = getModule();
2516 if (!m)
2517 m = sc->module;
2518 if (m)
2519 { m->needmoduleinfo = 1;
2520 #ifdef IN_GCC
2521 m->strictlyneedmoduleinfo = 1;
2522 #endif
2526 AggregateDeclaration *StaticDtorDeclaration::isThis()
2528 return NULL;
2531 int StaticDtorDeclaration::isStaticDestructor()
2533 return TRUE;
2536 int StaticDtorDeclaration::isVirtual()
2538 return FALSE;
2541 int StaticDtorDeclaration::addPreInvariant()
2543 return FALSE;
2546 int StaticDtorDeclaration::addPostInvariant()
2548 return FALSE;
2551 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2553 if (hgs->hdrgen)
2554 return;
2555 buf->writestring("static ~this()");
2556 bodyToCBuffer(buf, hgs);
2559 /********************************* InvariantDeclaration ****************************/
2561 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
2562 : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
2566 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
2568 InvariantDeclaration *id;
2570 assert(!s);
2571 id = new InvariantDeclaration(loc, endloc);
2572 FuncDeclaration::syntaxCopy(id);
2573 return id;
2577 void InvariantDeclaration::semantic(Scope *sc)
2579 AggregateDeclaration *ad;
2580 Type *tret;
2582 parent = sc->parent;
2583 Dsymbol *parent = toParent();
2584 ad = parent->isAggregateDeclaration();
2585 if (!ad)
2587 error("invariants only are for struct/union/class definitions");
2588 return;
2590 else if (ad->inv && ad->inv != this)
2592 error("more than one invariant for %s", ad->toChars());
2594 ad->inv = this;
2595 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2597 sc = sc->push();
2598 sc->stc &= ~STCstatic; // not a static invariant
2599 sc->incontract++;
2600 sc->linkage = LINKd;
2602 FuncDeclaration::semantic(sc);
2604 sc->pop();
2607 int InvariantDeclaration::isVirtual()
2609 return FALSE;
2612 int InvariantDeclaration::addPreInvariant()
2614 return FALSE;
2617 int InvariantDeclaration::addPostInvariant()
2619 return FALSE;
2622 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2624 if (hgs->hdrgen)
2625 return;
2626 buf->writestring("invariant");
2627 bodyToCBuffer(buf, hgs);
2631 /********************************* UnitTestDeclaration ****************************/
2633 /*******************************
2634 * Generate unique unittest function Id so we can have multiple
2635 * instances per module.
2638 static Identifier *unitTestId()
2640 static int n;
2641 char buffer[10 + sizeof(n)*3 + 1];
2643 sprintf(buffer,"__unittest%d", n);
2644 n++;
2645 return Lexer::idPool(buffer);
2648 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
2649 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
2653 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
2655 UnitTestDeclaration *utd;
2657 assert(!s);
2658 utd = new UnitTestDeclaration(loc, endloc);
2659 return FuncDeclaration::syntaxCopy(utd);
2663 void UnitTestDeclaration::semantic(Scope *sc)
2665 if (global.params.useUnitTests)
2667 Type *tret;
2669 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2670 FuncDeclaration::semantic(sc);
2673 // We're going to need ModuleInfo even if the unit tests are not
2674 // compiled in, because other modules may import this module and refer
2675 // to this ModuleInfo.
2676 Module *m = getModule();
2677 if (!m)
2678 m = sc->module;
2679 if (m)
2680 m->needmoduleinfo = 1;
2683 AggregateDeclaration *UnitTestDeclaration::isThis()
2685 return NULL;
2688 int UnitTestDeclaration::isVirtual()
2690 return FALSE;
2693 int UnitTestDeclaration::addPreInvariant()
2695 return FALSE;
2698 int UnitTestDeclaration::addPostInvariant()
2700 return FALSE;
2703 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2705 if (hgs->hdrgen)
2706 return;
2707 buf->writestring("unittest");
2708 bodyToCBuffer(buf, hgs);
2711 /********************************* NewDeclaration ****************************/
2713 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2714 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
2716 this->arguments = arguments;
2717 this->varargs = varargs;
2720 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
2722 NewDeclaration *f;
2724 f = new NewDeclaration(loc, endloc, NULL, varargs);
2726 FuncDeclaration::syntaxCopy(f);
2728 f->arguments = Argument::arraySyntaxCopy(arguments);
2730 return f;
2734 void NewDeclaration::semantic(Scope *sc)
2736 ClassDeclaration *cd;
2737 Type *tret;
2739 //printf("NewDeclaration::semantic()\n");
2741 parent = sc->parent;
2742 Dsymbol *parent = toParent();
2743 cd = parent->isClassDeclaration();
2744 if (!cd && !parent->isStructDeclaration())
2746 error("new allocators only are for class or struct definitions");
2748 tret = Type::tvoid->pointerTo();
2749 type = new TypeFunction(arguments, tret, varargs, LINKd);
2751 type = type->semantic(loc, sc);
2752 assert(type->ty == Tfunction);
2754 // Check that there is at least one argument of type uint
2755 TypeFunction *tf = (TypeFunction *)type;
2756 if (Argument::dim(tf->parameters) < 1)
2758 error("at least one argument of type uint expected");
2760 else
2762 Argument *a = Argument::getNth(tf->parameters, 0);
2763 if (!a->type->equals(Type::tuns32) &&
2764 (! global.params.isX86_64 || !a->type->equals(Type::tuns64)))
2765 error("first argument must be type uint, not %s", a->type->toChars());
2768 FuncDeclaration::semantic(sc);
2771 char *NewDeclaration::kind()
2773 return "allocator";
2776 int NewDeclaration::isVirtual()
2778 return FALSE;
2781 int NewDeclaration::addPreInvariant()
2783 return FALSE;
2786 int NewDeclaration::addPostInvariant()
2788 return FALSE;
2791 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2793 buf->writestring("new");
2794 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2795 bodyToCBuffer(buf, hgs);
2799 /********************************* DeleteDeclaration ****************************/
2801 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
2802 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
2804 this->arguments = arguments;
2807 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
2809 DeleteDeclaration *f;
2811 f = new DeleteDeclaration(loc, endloc, NULL);
2813 FuncDeclaration::syntaxCopy(f);
2815 f->arguments = Argument::arraySyntaxCopy(arguments);
2817 return f;
2821 void DeleteDeclaration::semantic(Scope *sc)
2823 ClassDeclaration *cd;
2825 //printf("DeleteDeclaration::semantic()\n");
2827 parent = sc->parent;
2828 Dsymbol *parent = toParent();
2829 cd = parent->isClassDeclaration();
2830 if (!cd && !parent->isStructDeclaration())
2832 error("new allocators only are for class or struct definitions");
2834 type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
2836 type = type->semantic(loc, sc);
2837 assert(type->ty == Tfunction);
2839 // Check that there is only one argument of type void*
2840 TypeFunction *tf = (TypeFunction *)type;
2841 if (Argument::dim(tf->parameters) != 1)
2843 error("one argument of type void* expected");
2845 else
2847 Argument *a = Argument::getNth(tf->parameters, 0);
2848 if (!a->type->equals(Type::tvoid->pointerTo()))
2849 error("one argument of type void* expected, not %s", a->type->toChars());
2852 FuncDeclaration::semantic(sc);
2855 char *DeleteDeclaration::kind()
2857 return "deallocator";
2860 int DeleteDeclaration::isDelete()
2862 return TRUE;
2865 int DeleteDeclaration::isVirtual()
2867 return FALSE;
2870 int DeleteDeclaration::addPreInvariant()
2872 return FALSE;
2875 int DeleteDeclaration::addPostInvariant()
2877 return FALSE;
2880 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2882 buf->writestring("delete");
2883 Argument::argsToCBuffer(buf, hgs, arguments, 0);
2884 bodyToCBuffer(buf, hgs);