Check that all non-null fields in a class get initialised by the constructor
[delight/core.git] / dmd / func.c
blob85d51be295c9432a30171c0f12559d7682f0612b
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 #endif
323 if (fdv->toParent() == parent)
325 // If both are mixins, then error.
326 // If either is not, the one that is not overrides
327 // the other.
328 if (fdv->parent->isClassDeclaration())
329 break;
330 if (!this->parent->isClassDeclaration()
331 #if !BREAKABI
332 && !isDtorDeclaration()
333 #endif
334 #if V2
335 && !isPostBlitDeclaration()
336 #endif
338 error("multiple overrides of same function");
340 cd->vtbl.data[vi] = (void *)this;
341 vtblIndex = vi;
343 /* This works by whenever this function is called,
344 * it actually returns tintro, which gets dynamically
345 * cast to type. But we know that tintro is a base
346 * of type, so we could optimize it by not doing a
347 * dynamic cast, but just subtracting the isBaseOf()
348 * offset if the value is != null.
351 if (fdv->tintro)
352 tintro = fdv->tintro;
353 else if (!type->equals(fdv->type))
355 /* Only need to have a tintro if the vptr
356 * offsets differ
358 target_ptrdiff_t offset;
359 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
361 tintro = fdv->type;
364 break;
368 /* Go through all the interface bases.
369 * If this function is covariant with any members of those interface
370 * functions, set the tintro.
372 for (int i = 0; i < cd->interfaces_dim; i++)
374 #if 1
375 BaseClass *b = cd->interfaces[i];
376 vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
377 switch (vi)
379 case -1:
380 break;
382 case -2:
383 cd->sizeok = 2; // can't finish due to forward reference
384 return;
386 default:
387 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
388 Type *ti = NULL;
390 if (fdv->tintro)
391 ti = fdv->tintro;
392 else if (!type->equals(fdv->type))
394 /* Only need to have a tintro if the vptr
395 * offsets differ
397 target_ptrdiff_t offset;
398 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
400 ti = fdv->type;
401 #if 0
402 if (offset)
403 ti = fdv->type;
404 else if (type->nextOf()->ty == Tclass)
405 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
406 if (cdn && cdn->sizeok != 1)
407 ti = fdv->type;
409 #endif
412 if (ti)
414 if (tintro && !tintro->equals(ti))
416 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
418 tintro = ti;
420 goto L2;
423 #else
424 BaseClass *b = cd->interfaces[i];
425 for (vi = 0; vi < b->base->vtbl.dim; vi++)
427 Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
428 //printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
429 FuncDeclaration *fdv = s->isFuncDeclaration();
430 if (fdv && fdv->ident == ident)
432 int cov = type->covariant(fdv->type);
433 //printf("\tcov = %d\n", cov);
434 if (cov == 2)
436 //type->print();
437 //fdv->type->print();
438 //printf("%s %s\n", type->deco, fdv->type->deco);
439 error("of type %s overrides but is not covariant with %s of type %s",
440 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
442 if (cov == 1)
443 { Type *ti = NULL;
445 if (fdv->tintro)
446 ti = fdv->tintro;
447 else if (!type->equals(fdv->type))
449 /* Only need to have a tintro if the vptr
450 * offsets differ
452 target_ptrdiff_t offset;
453 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
455 ti = fdv->type;
456 #if 0
457 if (offset)
458 ti = fdv->type;
459 else if (type->nextOf()->ty == Tclass)
460 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
461 if (cdn && cdn->sizeok != 1)
462 ti = fdv->type;
464 #endif
467 if (ti)
469 if (tintro && !tintro->equals(ti))
471 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
473 tintro = ti;
475 goto L2;
477 if (cov == 3)
479 cd->sizeok = 2; // can't finish due to forward reference
480 return;
484 #endif
487 if (introducing && isOverride())
489 error("does not override any function");
492 L2: ;
494 else if (isOverride() && !parent->isTemplateInstance())
495 error("override only applies to class member functions");
497 /* Do not allow template instances to add virtual functions
498 * to a class.
500 if (isVirtual())
502 TemplateInstance *ti = parent->isTemplateInstance();
503 if (ti)
505 // Take care of nested templates
506 while (1)
508 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
509 if (!ti2)
510 break;
511 ti = ti2;
514 // If it's a member template
515 ClassDeclaration *cd = ti->tempdecl->isClassMember();
516 if (cd)
518 error("cannot use template to add virtual function to class '%s'", cd->toChars());
523 if (isMain())
525 // Check parameters to see if they are either () or (char[][] args)
526 switch (nparams)
528 case 0:
529 break;
531 case 1:
533 Argument *arg0 = Argument::getNth(f->parameters, 0);
534 if (arg0->type->ty != Tarray ||
535 arg0->type->nextOf()->ty != Tarray ||
536 arg0->type->nextOf()->nextOf()->ty != Tchar ||
537 arg0->storageClass & (STCout | STCref | STClazy))
538 goto Lmainerr;
539 break;
542 default:
543 goto Lmainerr;
546 if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
547 error("must return int or void, not %s", f->nextOf()->toChars());
548 if (f->varargs)
550 Lmainerr:
551 error("parameters must be main() or main(char[][] args)");
555 if (ident == Id::assign && (sd || cd))
556 { // Disallow identity assignment operator.
558 // opAssign(...)
559 if (nparams == 0)
560 { if (f->varargs == 1)
561 goto Lassignerr;
563 else
565 Argument *arg0 = Argument::getNth(f->parameters, 0);
566 Type *t0 = arg0->type->toBasetype();
567 Type *tb = sd ? sd->type : cd->type;
568 if (arg0->type->implicitConvTo(tb) ||
569 (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
572 if (nparams == 1)
573 goto Lassignerr;
574 Argument *arg1 = Argument::getNth(f->parameters, 1);
575 if (arg1->defaultArg)
576 goto Lassignerr;
581 Ldone:
582 /* Save scope for possible later use (if we need the
583 * function internals)
585 scope = new Scope(*sc);
586 scope->setNoFree();
587 return;
589 Lassignerr:
590 error("identity assignment operator overload is illegal");
593 void FuncDeclaration::semantic2(Scope *sc)
597 // Do the semantic analysis on the internals of the function.
599 void FuncDeclaration::semantic3(Scope *sc)
600 { TypeFunction *f;
601 AggregateDeclaration *ad;
602 VarDeclaration *argptr = NULL;
603 VarDeclaration *_arguments = NULL;
605 if (!parent)
607 if (global.errors)
608 return;
609 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
610 assert(0);
612 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
613 //fflush(stdout);
614 //{ static int x; if (++x == 2) *(char*)0=0; }
615 //printf("\tlinkage = %d\n", sc->linkage);
617 //printf(" sc->incontract = %d\n", sc->incontract);
618 if (semanticRun)
619 return;
620 semanticRun = 1;
622 if (!type || type->ty != Tfunction)
623 return;
624 f = (TypeFunction *)(type);
625 size_t nparams = Argument::dim(f->parameters);
627 // Check the 'throws' clause
628 if (fthrows)
629 { int i;
631 for (i = 0; i < fthrows->dim; i++)
633 Type *t = (Type *)fthrows->data[i];
635 t = t->semantic(loc, sc);
636 if (!t->isClassHandle())
637 error("can only throw classes, not %s", t->toChars());
641 if (fbody || frequire)
643 /* Symbol table into which we place parameters and nested functions,
644 * solely to diagnose name collisions.
646 localsymtab = new DsymbolTable();
648 // Establish function scope
649 ScopeDsymbol *ss = new ScopeDsymbol();
650 ss->parent = sc->scopesym;
651 Scope *sc2 = sc->push(ss);
652 sc2->func = this;
653 sc2->parent = this;
654 sc2->callSuper = 0;
655 sc2->sbreak = NULL;
656 sc2->scontinue = NULL;
657 sc2->sw = NULL;
658 sc2->fes = fes;
659 sc2->linkage = LINKd;
660 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCfinal);
661 sc2->attributes = NULL;
662 sc2->protection = PROTpublic;
663 sc2->explicitProtection = 0;
664 sc2->structalign = 8;
665 sc2->incontract = 0;
666 sc2->tf = NULL;
667 sc2->noctor = 0;
669 // Declare 'this'
670 ad = isThis();
671 if (ad)
672 { VarDeclaration *v;
674 if (isFuncLiteralDeclaration() && isNested())
676 error("literals cannot be class members");
677 return;
679 else
681 assert(!isNested()); // can't be both member and nested
682 assert(ad->handle);
683 v = new ThisDeclaration(ad->handle);
684 v->storage_class |= STCparameter | STCin;
685 v->semantic(sc2);
686 if (!sc2->insert(v))
687 assert(0);
688 v->parent = this;
689 vthis = v;
692 else if (isNested())
694 VarDeclaration *v;
696 v = new ThisDeclaration(Type::tvoid->pointerTo());
697 v->storage_class |= STCparameter | STCin;
698 v->semantic(sc2);
699 if (!sc2->insert(v))
700 assert(0);
701 v->parent = this;
702 vthis = v;
705 // Declare hidden variable _arguments[] and _argptr
706 if (f->varargs == 1)
707 { Type *t;
709 if (f->linkage == LINKd)
710 { // Declare _arguments[]
711 #if BREAKABI
712 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
713 v_arguments->storage_class = STCparameter | STCin;
714 v_arguments->semantic(sc2);
715 sc2->insert(v_arguments);
716 v_arguments->parent = this;
718 t = Type::typeinfo->type->arrayOf();
719 _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
720 _arguments->semantic(sc2);
721 sc2->insert(_arguments);
722 _arguments->parent = this;
723 #else
724 t = Type::typeinfo->type->arrayOf();
725 v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
726 v_arguments->storage_class = STCparameter | STCin;
727 v_arguments->semantic(sc2);
728 sc2->insert(v_arguments);
729 v_arguments->parent = this;
730 #endif
732 if (f->linkage == LINKd || (parameters && parameters->dim))
733 { // Declare _argptr
734 #if IN_GCC
735 t = d_gcc_builtin_va_list_d_type;
736 #else
737 t = Type::tvoid->pointerTo();
738 #endif
739 argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
740 argptr->semantic(sc2);
741 sc2->insert(argptr);
742 argptr->parent = this;
746 // Propagate storage class from tuple parameters to their element-parameters.
747 if (f->parameters)
749 for (size_t i = 0; i < f->parameters->dim; i++)
750 { Argument *arg = (Argument *)f->parameters->data[i];
752 if (arg->type->ty == Ttuple)
753 { TypeTuple *t = (TypeTuple *)arg->type;
754 size_t dim = Argument::dim(t->arguments);
755 for (size_t j = 0; j < dim; j++)
756 { Argument *narg = Argument::getNth(t->arguments, j);
757 narg->storageClass = arg->storageClass;
763 // Declare all the function parameters as variables
764 if (nparams)
765 { /* parameters[] has all the tuples removed, as the back end
766 * doesn't know about tuples
768 parameters = new Dsymbols();
769 parameters->reserve(nparams);
770 for (size_t i = 0; i < nparams; i++)
772 Argument *arg = Argument::getNth(f->parameters, i);
773 Identifier *id = arg->ident;
774 if (!id)
776 /* Generate identifier for un-named parameter,
777 * because we need it later on.
779 OutBuffer buf;
780 buf.printf("_param_%"PRIuSIZE, i);
781 char *name = (char *)buf.extractData();
782 id = new Identifier(name, TOKidentifier);
783 arg->ident = id;
785 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
786 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
787 v->storage_class |= STCparameter;
788 if (f->varargs == 2 && i + 1 == nparams)
789 v->storage_class |= STCvariadic;
790 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy);
791 if (v->storage_class & STClazy)
792 v->storage_class |= STCin;
793 v->semantic(sc2);
794 if (!sc2->insert(v))
795 error("parameter %s.%s is already defined", toChars(), v->toChars());
796 else
797 parameters->push(v);
798 localsymtab->insert(v);
799 v->parent = this;
803 // Declare the tuple symbols and put them in the symbol table,
804 // but not in parameters[].
805 if (f->parameters)
807 for (size_t i = 0; i < f->parameters->dim; i++)
808 { Argument *arg = (Argument *)f->parameters->data[i];
810 if (!arg->ident)
811 continue; // never used, so ignore
812 if (arg->type->ty == Ttuple)
813 { TypeTuple *t = (TypeTuple *)arg->type;
814 size_t dim = Argument::dim(t->arguments);
815 Objects *exps = new Objects();
816 exps->setDim(dim);
817 for (size_t j = 0; j < dim; j++)
818 { Argument *narg = Argument::getNth(t->arguments, j);
819 assert(narg->ident);
820 VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
821 assert(v);
822 Expression *e = new VarExp(0, v);
823 exps->data[j] = (void *)e;
825 assert(arg->ident);
826 TupleDeclaration *v = new TupleDeclaration(0, arg->ident, exps);
827 //printf("declaring tuple %s\n", v->toChars());
828 v->isexp = 1;
829 if (!sc2->insert(v))
830 error("parameter %s.%s is already defined", toChars(), v->toChars());
831 localsymtab->insert(v);
832 v->parent = this;
837 /* Do the semantic analysis on the [in] preconditions and
838 * [out] postconditions.
840 sc2->incontract++;
842 if (frequire)
843 { /* frequire is composed of the [in] contracts
845 // BUG: need to error if accessing out parameters
846 // BUG: need to treat parameters as const
847 // BUG: need to disallow returns and throws
848 // BUG: verify that all in and ref parameters are read
849 frequire = frequire->semantic(sc2);
850 labtab = NULL; // so body can't refer to labels
853 if (fensure || addPostInvariant())
854 { /* fensure is composed of the [out] contracts
856 ScopeDsymbol *sym = new ScopeDsymbol();
857 sym->parent = sc2->scopesym;
858 sc2 = sc2->push(sym);
860 assert(type->nextOf());
861 if (type->nextOf()->ty == Tvoid)
863 if (outId)
864 error("void functions have no result");
866 else
868 if (!outId)
869 outId = Id::result; // provide a default
872 if (outId)
873 { // Declare result variable
874 VarDeclaration *v;
875 Loc loc = this->loc;
877 if (fensure)
878 loc = fensure->loc;
880 v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
881 v->noauto = 1;
882 v->skipnullcheck = 1;
883 sc2->incontract--;
884 v->semantic(sc2);
885 sc2->incontract++;
886 if (!sc2->insert(v))
887 error("out result %s is already defined", v->toChars());
888 v->parent = this;
889 vresult = v;
891 // vresult gets initialized with the function return value
892 // in ReturnStatement::semantic()
895 // BUG: need to treat parameters as const
896 // BUG: need to disallow returns and throws
897 if (fensure)
898 { fensure = fensure->semantic(sc2);
899 labtab = NULL; // so body can't refer to labels
902 if (!global.params.useOut)
903 { fensure = NULL; // discard
904 vresult = NULL;
907 // Postcondition invariant
908 if (addPostInvariant())
910 Expression *e = NULL;
911 if (isCtorDeclaration())
913 // Call invariant directly only if it exists
914 InvariantDeclaration *inv = ad->inv;
915 ClassDeclaration *cd = ad->isClassDeclaration();
917 while (!inv && cd)
919 cd = cd->baseClass;
920 if (!cd)
921 break;
922 inv = cd->inv;
924 if (inv)
926 e = new DsymbolExp(0, inv);
927 e = new CallExp(0, e);
928 e = e->semantic(sc2);
931 else
932 { // Call invariant virtually
933 ThisExp *v = new ThisExp(0);
934 v->type = vthis->type;
935 e = new AssertExp(0, v);
937 if (e)
939 ExpStatement *s = new ExpStatement(0, e);
940 if (fensure)
941 fensure = new CompoundStatement(0, s, fensure);
942 else
943 fensure = s;
947 if (fensure)
948 { returnLabel = new LabelDsymbol(Id::returnLabel);
949 LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
950 ls->isReturnLabel = 1;
951 returnLabel->statement = ls;
953 sc2 = sc2->pop();
956 sc2->incontract--;
958 if (fbody)
959 { ClassDeclaration *cd = isClassMember();
961 /* If this is a class constructor
963 if (isCtorDeclaration() && cd)
965 for (int i = 0; i < cd->fields.dim; i++)
966 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
968 v->ctorinit = 0;
972 if (inferRetType || f->retStyle() != RETstack)
973 nrvo_can = 0;
975 fbody = fbody->semantic(sc2);
977 if (inferRetType)
978 { // If no return type inferred yet, then infer a void
979 if (!type->nextOf())
981 ((TypeFunction *)type)->next = Type::tvoid;
982 type = type->semantic(loc, sc);
984 f = (TypeFunction *)type;
987 int offend = fbody ? fbody->fallOffEnd() : TRUE;
989 if (isStaticCtorDeclaration())
990 { /* It's a static constructor. Ensure that all
991 * ctor consts were initialized.
994 Dsymbol *p = toParent();
995 ScopeDsymbol *ad = p->isScopeDsymbol();
996 if (!ad)
998 error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
1000 else
1002 for (int i = 0; i < ad->members->dim; i++)
1003 { Dsymbol *s = (Dsymbol *)ad->members->data[i];
1005 s->checkCtorConstInit();
1010 if (isCtorDeclaration() && cd)
1012 //printf("callSuper = x%x\n", sc2->callSuper);
1014 // Verify that all the ctorinit fields got initialized
1015 // Also check that non-null members got set
1016 if (!(sc2->callSuper & CSXthis_ctor))
1018 for (int i = 0; i < cd->fields.dim; i++)
1019 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
1021 if (v->ctorinit == 0)
1023 if (v->isCtorinit())
1024 error("missing initializer for const field %s", v->toChars());
1025 else if (v->type->ty == Tclass || v->type->ty == Tpointer)
1026 error("missing initializer for non-null field %s", v->toChars());
1031 if (!(sc2->callSuper & CSXany_ctor) &&
1032 cd->baseClass && cd->baseClass->ctor)
1034 sc2->callSuper = 0;
1036 // Insert implicit super() at start of fbody
1037 Expression *e1 = new SuperExp(0);
1038 Expression *e = new CallExp(0, e1);
1040 unsigned errors = global.errors;
1041 global.gag++;
1042 e = e->semantic(sc2);
1043 global.gag--;
1044 if (errors != global.errors)
1045 error("no match for implicit super() call in constructor");
1047 Statement *s = new ExpStatement(0, e);
1048 fbody = new CompoundStatement(0, s, fbody);
1051 else if (fes)
1052 { // For foreach(){} body, append a return 0;
1053 Expression *e = new IntegerExp(0);
1054 Statement *s = new ReturnStatement(0, e);
1055 fbody = new CompoundStatement(0, fbody, s);
1056 assert(!returnLabel);
1058 else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1059 error("expected to return a value of type %s", type->nextOf()->toChars());
1060 else if (!inlineAsm)
1062 if (type->nextOf()->ty == Tvoid)
1064 if (offend && isMain())
1065 { // Add a return 0; statement
1066 Statement *s = new ReturnStatement(0, new IntegerExp(0));
1067 fbody = new CompoundStatement(0, fbody, s);
1070 else
1072 if (offend)
1073 { Expression *e;
1075 if (global.params.warnings)
1076 { fprintf(stdmsg, "warning - ");
1077 error("no return at end of function");
1080 if (global.params.useAssert &&
1081 !global.params.useInline)
1082 { /* Add an assert(0, msg); where the missing return
1083 * should be.
1085 e = new AssertExp(
1086 endloc,
1087 new IntegerExp(0),
1088 new StringExp(loc, "missing return expression")
1091 else
1092 e = new HaltExp(endloc);
1093 e = new CommaExp(0, e, type->nextOf()->defaultInit());
1094 e = e->semantic(sc2);
1095 Statement *s = new ExpStatement(0, e);
1096 fbody = new CompoundStatement(0, fbody, s);
1103 Statements *a = new Statements();
1105 // Merge in initialization of 'out' parameters
1106 if (parameters)
1107 { for (size_t i = 0; i < parameters->dim; i++)
1109 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1110 if (v->storage_class & STCout)
1112 assert(v->init);
1113 ExpInitializer *ie = v->init->isExpInitializer();
1114 assert(ie);
1115 a->push(new ExpStatement(0, ie->exp));
1120 if (argptr)
1121 { // Initialize _argptr to point past non-variadic arg
1122 #if IN_GCC
1123 // Handled in FuncDeclaration::toObjFile
1124 v_argptr = argptr;
1125 v_argptr->init = new VoidInitializer(loc);
1126 #else
1127 Expression *e1;
1128 Expression *e;
1129 Type *t = argptr->type;
1130 VarDeclaration *p;
1131 unsigned offset;
1133 e1 = new VarExp(0, argptr);
1134 if (parameters && parameters->dim)
1135 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1136 else
1137 p = v_arguments; // last parameter is _arguments[]
1138 offset = p->type->size();
1139 offset = (offset + 3) & ~3; // assume stack aligns on 4
1140 e = new SymOffExp(0, p, offset);
1141 e = new AssignExp(0, e1, e);
1142 e->type = t;
1143 a->push(new ExpStatement(0, e));
1144 #endif
1147 if (_arguments)
1149 #if IN_GCC
1150 v_arguments_var = _arguments;
1151 v_arguments_var->init = new VoidInitializer(loc);
1152 #endif
1153 /* Advance to elements[] member of TypeInfo_Tuple with:
1154 * _arguments = v_arguments.elements;
1156 Expression *e = new VarExp(0, v_arguments);
1157 e = new DotIdExp(0, e, Id::elements);
1158 Expression *e1 = new VarExp(0, _arguments);
1159 e = new AssignExp(0, e1, e);
1160 e = e->semantic(sc);
1161 a->push(new ExpStatement(0, e));
1164 // Merge contracts together with body into one compound statement
1166 #ifdef _DH
1167 if (frequire && global.params.useIn)
1168 { frequire->incontract = 1;
1169 a->push(frequire);
1171 #else
1172 if (frequire && global.params.useIn)
1173 a->push(frequire);
1174 #endif
1176 // Precondition invariant
1177 if (addPreInvariant())
1179 Expression *e = NULL;
1180 if (isDtorDeclaration())
1182 // Call invariant directly only if it exists
1183 InvariantDeclaration *inv = ad->inv;
1184 ClassDeclaration *cd = ad->isClassDeclaration();
1186 while (!inv && cd)
1188 cd = cd->baseClass;
1189 if (!cd)
1190 break;
1191 inv = cd->inv;
1193 if (inv)
1195 e = new DsymbolExp(0, inv);
1196 e = new CallExp(0, e);
1197 e = e->semantic(sc2);
1200 else
1201 { // Call invariant virtually
1202 ThisExp *v = new ThisExp(0);
1203 v->type = vthis->type;
1204 Expression *se = new StringExp(0, "null this");
1205 se = se->semantic(sc);
1206 se->type = Type::tchar->arrayOf();
1207 e = new AssertExp(loc, v, se);
1209 if (e)
1211 ExpStatement *s = new ExpStatement(0, e);
1212 a->push(s);
1216 if (fbody)
1217 a->push(fbody);
1219 if (fensure)
1221 a->push(returnLabel->statement);
1223 if (type->nextOf()->ty != Tvoid)
1225 // Create: return vresult;
1226 assert(vresult);
1227 Expression *e = new VarExp(0, vresult);
1228 if (tintro)
1229 { e = e->implicitCastTo(sc, tintro->nextOf());
1230 e = e->semantic(sc);
1232 ReturnStatement *s = new ReturnStatement(0, e);
1233 a->push(s);
1237 fbody = new CompoundStatement(0, a);
1240 sc2->callSuper = 0;
1241 sc2->pop();
1243 semanticRun = 2;
1246 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1248 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1250 type->toCBuffer(buf, ident, hgs);
1251 bodyToCBuffer(buf, hgs);
1255 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1257 if (fbody &&
1258 (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1260 { buf->writenl();
1262 // in{}
1263 if (frequire)
1264 { buf->writestring("in");
1265 buf->writenl();
1266 frequire->toCBuffer(buf, hgs);
1269 // out{}
1270 if (fensure)
1271 { buf->writestring("out");
1272 if (outId)
1273 { buf->writebyte('(');
1274 buf->writestring(outId->toChars());
1275 buf->writebyte(')');
1277 buf->writenl();
1278 fensure->toCBuffer(buf, hgs);
1281 if (frequire || fensure)
1282 { buf->writestring("body");
1283 buf->writenl();
1286 buf->writebyte('{');
1287 buf->writenl();
1288 fbody->toCBuffer(buf, hgs);
1289 buf->writebyte('}');
1290 buf->writenl();
1292 else
1293 { buf->writeByte(';');
1294 buf->writenl();
1298 /****************************************************
1299 * Determine if 'this' overrides fd.
1300 * Return !=0 if it does.
1303 int FuncDeclaration::overrides(FuncDeclaration *fd)
1304 { int result = 0;
1306 if (fd->ident == ident)
1308 int cov = type->covariant(fd->type);
1309 if (cov)
1310 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1311 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1313 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1314 result = 1;
1317 return result;
1320 /*************************************************
1321 * Find index of function in vtbl[0..dim] that
1322 * this function overrides.
1323 * Returns:
1324 * -1 didn't find one
1325 * -2 can't determine because of forward references
1328 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
1330 for (int vi = 0; vi < dim; vi++)
1332 FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
1333 if (fdv && fdv->ident == ident)
1335 int cov = type->covariant(fdv->type);
1336 //printf("\tbaseclass cov = %d\n", cov);
1337 switch (cov)
1339 case 0: // types are distinct
1340 break;
1342 case 1:
1343 return vi;
1345 case 2:
1346 //type->print();
1347 //fdv->type->print();
1348 //printf("%s %s\n", type->deco, fdv->type->deco);
1349 error("of type %s overrides but is not covariant with %s of type %s",
1350 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
1351 break;
1353 case 3:
1354 return -2; // forward references
1356 default:
1357 assert(0);
1361 return -1;
1364 /****************************************************
1365 * Overload this FuncDeclaration with the new one f.
1366 * Return !=0 if successful; i.e. no conflict.
1369 int FuncDeclaration::overloadInsert(Dsymbol *s)
1371 FuncDeclaration *f;
1372 AliasDeclaration *a;
1374 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1375 a = s->isAliasDeclaration();
1376 if (a)
1378 if (overnext)
1379 return overnext->overloadInsert(a);
1380 if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1382 //printf("\ta = '%s'\n", a->type->toChars());
1383 return FALSE;
1385 overnext = a;
1386 //printf("\ttrue: no conflict\n");
1387 return TRUE;
1389 f = s->isFuncDeclaration();
1390 if (!f)
1391 return FALSE;
1393 if (type && f->type && // can be NULL for overloaded constructors
1394 f->type->covariant(type) &&
1395 !isFuncAliasDeclaration())
1397 //printf("\tfalse: conflict %s\n", kind());
1398 return FALSE;
1401 if (overnext)
1402 return overnext->overloadInsert(f);
1403 overnext = f;
1404 //printf("\ttrue: no conflict\n");
1405 return TRUE;
1408 /********************************************
1409 * Find function in overload list that exactly matches t.
1412 /***************************************************
1413 * Visit each overloaded function in turn, and call
1414 * (*fp)(param, f) on it.
1415 * Exit when no more, or (*fp)(param, f) returns 1.
1416 * Returns:
1417 * 0 continue
1418 * 1 done
1421 int overloadApply(FuncDeclaration *fstart,
1422 int (*fp)(void *, FuncDeclaration *),
1423 void *param)
1425 FuncDeclaration *f;
1426 Declaration *d;
1427 Declaration *next;
1429 for (d = fstart; d; d = next)
1430 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1432 if (fa)
1434 if (overloadApply(fa->funcalias, fp, param))
1435 return 1;
1436 next = fa->overnext;
1438 else
1440 AliasDeclaration *a = d->isAliasDeclaration();
1442 if (a)
1444 Dsymbol *s = a->toAlias();
1445 next = s->isDeclaration();
1446 if (next == a)
1447 break;
1448 if (next == fstart)
1449 break;
1451 else
1453 f = d->isFuncDeclaration();
1454 if (!f)
1455 { d->error("is aliased to a function");
1456 break; // BUG: should print error message?
1458 if ((*fp)(param, f))
1459 return 1;
1461 next = f->overnext;
1465 return 0;
1468 /********************************************
1469 * Find function in overload list that exactly matches t.
1472 struct Param1
1474 Type *t; // type to match
1475 FuncDeclaration *f; // return value
1478 int fp1(void *param, FuncDeclaration *f)
1479 { Param1 *p = (Param1 *)param;
1480 Type *t = p->t;
1482 if (t->equals(f->type))
1483 { p->f = f;
1484 return 1;
1487 #if V2
1488 /* Allow covariant matches, if it's just a const conversion
1489 * of the return type
1491 if (t->ty == Tfunction)
1492 { TypeFunction *tf = (TypeFunction *)f->type;
1493 if (tf->covariant(t) == 1 &&
1494 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
1496 p->f = f;
1497 return 1;
1500 #endif
1501 return 0;
1504 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1506 Param1 p;
1507 p.t = t;
1508 p.f = NULL;
1509 overloadApply(this, &fp1, &p);
1510 return p.f;
1513 #if 0
1514 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1516 FuncDeclaration *f;
1517 Declaration *d;
1518 Declaration *next;
1520 for (d = this; d; d = next)
1521 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1523 if (fa)
1525 FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t);
1526 if (f2)
1527 return f2;
1528 next = fa->overnext;
1530 else
1532 AliasDeclaration *a = d->isAliasDeclaration();
1534 if (a)
1536 Dsymbol *s = a->toAlias();
1537 next = s->isDeclaration();
1538 if (next == a)
1539 break;
1541 else
1543 f = d->isFuncDeclaration();
1544 if (!f)
1545 break; // BUG: should print error message?
1546 if (t->equals(d->type))
1547 return f;
1548 next = f->overnext;
1552 return NULL;
1554 #endif
1556 /********************************************
1557 * Decide which function matches the arguments best.
1560 struct Param2
1562 Match *m;
1563 Expressions *arguments;
1566 int fp2(void *param, FuncDeclaration *f)
1567 { Param2 *p = (Param2 *)param;
1568 Match *m = p->m;
1569 Expressions *arguments = p->arguments;
1570 MATCH match;
1572 if (f != m->lastf) // skip duplicates
1574 TypeFunction *tf;
1576 m->anyf = f;
1577 tf = (TypeFunction *)f->type;
1578 match = (MATCH) tf->callMatch(arguments);
1579 //printf("match = %d\n", match);
1580 if (match != MATCHnomatch)
1582 if (match > m->last)
1583 goto LfIsBetter;
1585 if (match < m->last)
1586 goto LlastIsBetter;
1588 /* See if one of the matches overrides the other.
1590 if (m->lastf->overrides(f))
1591 goto LlastIsBetter;
1592 else if (f->overrides(m->lastf))
1593 goto LfIsBetter;
1595 Lambiguous:
1596 m->nextf = f;
1597 m->count++;
1598 return 0;
1600 LfIsBetter:
1601 m->last = match;
1602 m->lastf = f;
1603 m->count = 1;
1604 return 0;
1606 LlastIsBetter:
1607 return 0;
1610 return 0;
1614 void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
1616 Param2 p;
1617 p.m = m;
1618 p.arguments = arguments;
1619 overloadApply(fstart, &fp2, &p);
1622 #if 0
1623 // Recursive helper function
1625 void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
1627 MATCH match;
1628 Declaration *d;
1629 Declaration *next;
1631 for (d = fstart; d; d = next)
1633 FuncDeclaration *f;
1634 FuncAliasDeclaration *fa;
1635 AliasDeclaration *a;
1637 fa = d->isFuncAliasDeclaration();
1638 if (fa)
1640 overloadResolveX(m, fa->funcalias, arguments);
1641 next = fa->overnext;
1643 else if ((f = d->isFuncDeclaration()) != NULL)
1645 next = f->overnext;
1646 if (f == m->lastf)
1647 continue; // skip duplicates
1648 else
1650 TypeFunction *tf;
1652 m->anyf = f;
1653 tf = (TypeFunction *)f->type;
1654 match = (MATCH) tf->callMatch(arguments);
1655 //printf("match = %d\n", match);
1656 if (match != MATCHnomatch)
1658 if (match > m->last)
1659 goto LfIsBetter;
1661 if (match < m->last)
1662 goto LlastIsBetter;
1664 /* See if one of the matches overrides the other.
1666 if (m->lastf->overrides(f))
1667 goto LlastIsBetter;
1668 else if (f->overrides(m->lastf))
1669 goto LfIsBetter;
1671 Lambiguous:
1672 m->nextf = f;
1673 m->count++;
1674 continue;
1676 LfIsBetter:
1677 m->last = match;
1678 m->lastf = f;
1679 m->count = 1;
1680 continue;
1682 LlastIsBetter:
1683 continue;
1687 else if ((a = d->isAliasDeclaration()) != NULL)
1689 Dsymbol *s = a->toAlias();
1690 next = s->isDeclaration();
1691 if (next == a)
1692 break;
1693 if (next == fstart)
1694 break;
1696 else
1697 { d->error("is aliased to a function");
1698 break;
1702 #endif
1704 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expressions *arguments)
1706 TypeFunction *tf;
1707 Match m;
1709 #if 0
1710 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1711 if (arguments)
1712 { int i;
1714 for (i = 0; i < arguments->dim; i++)
1715 { Expression *arg;
1717 arg = (Expression *)arguments->data[i];
1718 assert(arg->type);
1719 printf("\t%s: ", arg->toChars());
1720 arg->type->print();
1723 #endif
1725 memset(&m, 0, sizeof(m));
1726 m.last = MATCHnomatch;
1727 overloadResolveX(&m, this, arguments);
1729 if (m.count == 1) // exactly one match
1731 return m.lastf;
1733 else
1735 OutBuffer buf;
1737 if (arguments)
1739 HdrGenState hgs;
1741 argExpTypesToCBuffer(&buf, arguments, &hgs);
1744 if (m.last == MATCHnomatch)
1746 tf = (TypeFunction *)type;
1748 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1749 error(loc, "%s does not match parameter types (%s)",
1750 Argument::argsTypesToChars(tf->parameters, tf->varargs),
1751 buf.toChars());
1752 return m.anyf; // as long as it's not a FuncAliasDeclaration
1754 else
1756 #if 1
1757 TypeFunction *t1 = (TypeFunction *)m.lastf->type;
1758 TypeFunction *t2 = (TypeFunction *)m.nextf->type;
1760 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1761 buf.toChars(),
1762 m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
1763 m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
1764 #else
1765 error(loc, "overloads %s and %s both match argument list for %s",
1766 m.lastf->type->toChars(),
1767 m.nextf->type->toChars(),
1768 m.lastf->toChars());
1769 #endif
1770 return m.lastf;
1775 /********************************
1776 * Labels are in a separate scope, one per function.
1779 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
1780 { Dsymbol *s;
1782 if (!labtab)
1783 labtab = new DsymbolTable(); // guess we need one
1785 s = labtab->lookup(ident);
1786 if (!s)
1788 s = new LabelDsymbol(ident);
1789 labtab->insert(s);
1791 return (LabelDsymbol *)s;
1793 /****************************************
1794 * If non-static member function that has a 'this' pointer,
1795 * return the aggregate it is a member of.
1796 * Otherwise, return NULL.
1799 AggregateDeclaration *FuncDeclaration::isThis()
1800 { AggregateDeclaration *ad;
1802 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1803 ad = NULL;
1804 if ((storage_class & STCstatic) == 0)
1806 ad = isMember2();
1808 //printf("-FuncDeclaration::isThis() %p\n", ad);
1809 return ad;
1812 AggregateDeclaration *FuncDeclaration::isMember2()
1813 { AggregateDeclaration *ad;
1815 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1816 ad = NULL;
1817 for (Dsymbol *s = this; s; s = s->parent)
1819 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1820 ad = s->isMember();
1821 if (ad)
1822 { //printf("test4\n");
1823 break;
1825 if (!s->parent ||
1826 (!s->parent->isTemplateInstance()))
1827 { //printf("test5\n");
1828 break;
1831 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1832 return ad;
1835 /*****************************************
1836 * Determine lexical level difference from 'this' to nested function 'fd'.
1837 * Error if this cannot call fd.
1838 * Returns:
1839 * 0 same level
1840 * -1 increase nesting by 1 (fd is nested within 'this')
1841 * >0 decrease nesting by number
1844 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
1845 { int level;
1846 Dsymbol *s;
1847 Dsymbol *fdparent;
1849 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1850 fdparent = fd->toParent2();
1851 if (fdparent == this)
1852 return -1;
1853 s = this;
1854 level = 0;
1855 while (fd != s && fdparent != s->toParent2())
1857 //printf("\ts = '%s'\n", s->toChars());
1858 FuncDeclaration *thisfd = s->isFuncDeclaration();
1859 if (thisfd)
1860 { if (!thisfd->isNested() && !thisfd->vthis)
1861 goto Lerr;
1863 else
1865 ClassDeclaration *thiscd = s->isClassDeclaration();
1866 if (thiscd)
1867 { if (!thiscd->isNested())
1868 goto Lerr;
1870 else
1871 goto Lerr;
1874 s = s->toParent2();
1875 assert(s);
1876 level++;
1878 return level;
1880 Lerr:
1881 error(loc, "cannot access frame of function %s", fd->toChars());
1882 return 1;
1885 void FuncDeclaration::appendExp(Expression *e)
1886 { Statement *s;
1888 s = new ExpStatement(0, e);
1889 appendState(s);
1892 void FuncDeclaration::appendState(Statement *s)
1893 { CompoundStatement *cs;
1895 if (!fbody)
1896 { Statements *a;
1898 a = new Statements();
1899 fbody = new CompoundStatement(0, a);
1901 cs = fbody->isCompoundStatement();
1902 cs->statements->push(s);
1906 int FuncDeclaration::isMain()
1908 return ident == Id::main &&
1909 linkage != LINKc && !isMember() && !isNested();
1912 int FuncDeclaration::isWinMain()
1914 return ident == Id::WinMain &&
1915 linkage != LINKc && !isMember();
1918 int FuncDeclaration::isDllMain()
1920 return ident == Id::DllMain &&
1921 linkage != LINKc && !isMember();
1924 int FuncDeclaration::isExport()
1926 return protection == PROTexport;
1929 int FuncDeclaration::isImportedSymbol()
1931 //printf("isImportedSymbol()\n");
1932 //printf("protection = %d\n", protection);
1933 return (protection == PROTexport) && !fbody;
1936 // Determine if function goes into virtual function pointer table
1938 int FuncDeclaration::isVirtual()
1940 #if 0
1941 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1942 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
1943 printf("result is %d\n",
1944 isMember() &&
1945 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1946 toParent()->isClassDeclaration());
1947 #endif
1948 return isMember() &&
1949 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1950 toParent()->isClassDeclaration();
1953 int FuncDeclaration::isAbstract()
1955 return storage_class & STCabstract;
1958 int FuncDeclaration::isCodeseg()
1960 return TRUE; // functions are always in the code segment
1963 // Determine if function needs
1964 // a static frame pointer to its lexically enclosing function
1966 int FuncDeclaration::isNested()
1968 //if (!toParent())
1969 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
1970 //printf("\ttoParent() = '%s'\n", toParent()->toChars());
1971 return ((storage_class & STCstatic) == 0) &&
1972 (toParent2()->isFuncDeclaration() != NULL);
1975 int FuncDeclaration::needThis()
1977 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
1978 int i = isThis() != NULL;
1979 //printf("\t%d\n", i);
1980 if (!i && isFuncAliasDeclaration())
1981 i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
1982 return i;
1985 int FuncDeclaration::addPreInvariant()
1987 AggregateDeclaration *ad = isThis();
1988 return (ad &&
1989 //ad->isClassDeclaration() &&
1990 global.params.useInvariants &&
1991 (protection == PROTpublic || protection == PROTexport) &&
1992 !naked);
1995 int FuncDeclaration::addPostInvariant()
1997 AggregateDeclaration *ad = isThis();
1998 return (ad &&
1999 ad->inv &&
2000 //ad->isClassDeclaration() &&
2001 global.params.useInvariants &&
2002 (protection == PROTpublic || protection == PROTexport) &&
2003 !naked);
2006 /**********************************
2007 * Generate a FuncDeclaration for a runtime library function.
2010 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name,
2011 Type *t1, Type *t2, Type *t3)
2013 return genCfunc(treturn, Lexer::idPool(name), t1, t2, t3);
2016 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id,
2017 Type *t1, Type *t2, Type *t3)
2019 FuncDeclaration *fd;
2020 TypeFunction *tf;
2021 Dsymbol *s;
2022 static DsymbolTable *st = NULL;
2024 //printf("genCfunc(name = '%s')\n", id->toChars());
2025 //printf("treturn\n\t"); treturn->print();
2027 // See if already in table
2028 if (!st)
2029 st = new DsymbolTable();
2030 s = st->lookup(id);
2031 if (s)
2033 fd = s->isFuncDeclaration();
2034 assert(fd);
2035 assert(fd->type->nextOf()->equals(treturn));
2037 else
2039 Arguments * args = 0;
2040 if (t1) {
2041 args = new Arguments;
2042 args->push(new Argument(STCin,t1,0,0));
2043 if (t2)
2045 args->push(new Argument(STCin,t2,0,0));
2046 if (t3)
2047 args->push(new Argument(STCin,t3,0,0));
2051 tf = new TypeFunction(args, treturn, 0, LINKc);
2052 fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2053 fd->protection = PROTpublic;
2054 fd->linkage = LINKc;
2056 st->insert(fd);
2058 return fd;
2061 char *FuncDeclaration::kind()
2063 return "function";
2065 /*******************************
2066 * Look at all the variables in this function that are referenced
2067 * by nested functions, and determine if a closure needs to be
2068 * created for them.
2071 #if V2
2072 int FuncDeclaration::needsClosure()
2074 /* Need a closure for all the closureVars[] if any of the
2075 * closureVars[] are accessed by a
2076 * function that escapes the scope of this function.
2077 * We take the conservative approach and decide that any function that:
2078 * 1) is a virtual function
2079 * 2) has its address taken
2080 * 3) has a parent that escapes
2081 * escapes.
2084 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2085 for (int i = 0; i < closureVars.dim; i++)
2086 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
2087 assert(v->isVarDeclaration());
2088 //printf("\tv = %s\n", v->toChars());
2090 for (int j = 0; j < v->nestedrefs.dim; j++)
2091 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
2092 assert(f != this);
2094 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2095 if (f->isVirtual() || f->tookAddressOf)
2096 goto Lyes; // assume f escapes this function's scope
2098 // Look to see if any parents of f that are below this escape
2099 for (Dsymbol *s = f->parent; s != this; s = s->parent)
2101 f = s->isFuncDeclaration();
2102 if (f && (f->isVirtual() || f->tookAddressOf))
2103 goto Lyes;
2107 return 0;
2109 Lyes:
2110 //printf("\tneeds closure\n");
2111 return 1;
2113 #endif
2115 /****************************** FuncAliasDeclaration ************************/
2117 // Used as a way to import a set of functions from another scope into this one.
2119 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2120 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2121 (enum STC)funcalias->storage_class, funcalias->type)
2123 assert(funcalias != this);
2124 this->funcalias = funcalias;
2127 char *FuncAliasDeclaration::kind()
2129 return "function alias";
2133 /****************************** FuncLiteralDeclaration ************************/
2135 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2136 enum TOK tok, ForeachStatement *fes)
2137 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2139 char *id;
2141 if (fes)
2142 id = "__foreachbody";
2143 else if (tok == TOKdelegate)
2144 id = "__dgliteral";
2145 else
2146 id = "__funcliteral";
2147 this->ident = Identifier::generateId(id);
2148 this->tok = tok;
2149 this->fes = fes;
2150 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2153 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2155 FuncLiteralDeclaration *f;
2157 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2158 if (s)
2159 f = (FuncLiteralDeclaration *)s;
2160 else
2161 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2162 FuncDeclaration::syntaxCopy(f);
2163 return f;
2166 int FuncLiteralDeclaration::isNested()
2168 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2169 return (tok == TOKdelegate);
2172 char *FuncLiteralDeclaration::kind()
2174 // GCC requires the (char*) casts
2175 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
2178 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2180 static Identifier *idfunc;
2181 static Identifier *iddel;
2183 if (!idfunc)
2184 idfunc = new Identifier("function", 0);
2185 if (!iddel)
2186 iddel = new Identifier("delegate", 0);
2188 type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
2189 bodyToCBuffer(buf, hgs);
2193 /********************************* CtorDeclaration ****************************/
2195 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2196 : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
2198 this->arguments = arguments;
2199 this->varargs = varargs;
2200 //printf("CtorDeclaration() %s\n", toChars());
2203 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2205 CtorDeclaration *f;
2207 f = new CtorDeclaration(loc, endloc, NULL, varargs);
2209 f->outId = outId;
2210 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2211 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
2212 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
2213 assert(!fthrows); // deprecated
2215 f->arguments = Argument::arraySyntaxCopy(arguments);
2216 return f;
2220 void CtorDeclaration::semantic(Scope *sc)
2222 ClassDeclaration *cd;
2223 Type *tret;
2225 //printf("CtorDeclaration::semantic()\n");
2226 if (type)
2227 return;
2229 sc = sc->push();
2230 sc->stc &= ~STCstatic; // not a static constructor
2232 parent = sc->parent;
2233 Dsymbol *parent = toParent();
2234 cd = parent->isClassDeclaration();
2235 if (!cd)
2237 error("constructors are only for class definitions");
2238 tret = Type::tvoid;
2240 else
2242 tret = cd->type; //->referenceTo();
2244 for (int i = 0; i < cd->fields.dim; i++)
2246 VarDeclaration *vd = (VarDeclaration *) cd->fields.data[i];
2247 if (vd->isIn())
2249 if (!arguments)
2250 arguments = new Arguments();
2251 Argument *a = new Argument(vd->storage_class, vd->type, vd->ident, 0);
2252 // BUG: We don't really want these arguments in scope...
2253 arguments->push(a);
2255 Statement *assign = new ExpStatement(loc, new AssignExp(loc,
2256 new DotIdExp(loc, new ThisExp(loc), a->ident),
2257 new IdentifierExp(loc, a->ident)));
2258 if (fbody)
2259 fbody = new CompoundStatement(loc, assign, fbody);
2260 else
2261 fbody = assign;
2266 type = new TypeFunction(arguments, tret, varargs, LINKd);
2268 sc->flags |= SCOPEctor;
2269 type = type->semantic(loc, sc);
2270 sc->flags &= ~SCOPEctor;
2272 // Append:
2273 // return this;
2274 // to the function body
2275 if (fbody)
2276 { Expression *e;
2277 Statement *s;
2279 e = new ThisExp(0);
2280 s = new ReturnStatement(0, e);
2281 fbody = new CompoundStatement(0, fbody, s);
2284 FuncDeclaration::semantic(sc);
2286 sc->pop();
2288 // See if it's the default constructor
2289 if (cd && varargs == 0 && Argument::dim(arguments) == 0)
2290 cd->defaultCtor = this;
2293 char *CtorDeclaration::kind()
2295 return "constructor";
2298 char *CtorDeclaration::toChars()
2300 return "this";
2303 int CtorDeclaration::isVirtual()
2305 return FALSE;
2308 int CtorDeclaration::addPreInvariant()
2310 return FALSE;
2313 int CtorDeclaration::addPostInvariant()
2315 return (vthis && global.params.useInvariants);
2319 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2321 buf->writestring("this");
2322 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2323 bodyToCBuffer(buf, hgs);
2326 /********************************* DtorDeclaration ****************************/
2328 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
2329 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
2333 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
2334 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2338 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
2340 assert(!s);
2341 DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
2342 return FuncDeclaration::syntaxCopy(dd);
2346 void DtorDeclaration::semantic(Scope *sc)
2348 ClassDeclaration *cd;
2350 parent = sc->parent;
2351 Dsymbol *parent = toParent();
2352 cd = parent->isClassDeclaration();
2353 if (!cd)
2355 error("destructors only are for class definitions");
2357 else
2358 cd->dtors.push(this);
2359 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2361 sc = sc->push();
2362 sc->stc &= ~STCstatic; // not a static destructor
2363 sc->linkage = LINKd;
2365 FuncDeclaration::semantic(sc);
2367 sc->pop();
2370 int DtorDeclaration::overloadInsert(Dsymbol *s)
2372 return FALSE; // cannot overload destructors
2375 int DtorDeclaration::addPreInvariant()
2377 return (vthis && global.params.useInvariants);
2380 int DtorDeclaration::addPostInvariant()
2382 return FALSE;
2385 int DtorDeclaration::isVirtual()
2387 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2388 * but doing so will require recompiling everything.
2390 #if BREAKABI
2391 return FALSE;
2392 #else
2393 return FuncDeclaration::isVirtual();
2394 #endif
2397 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2399 if (hgs->hdrgen)
2400 return;
2401 buf->writestring("~this()");
2402 bodyToCBuffer(buf, hgs);
2405 /********************************* StaticCtorDeclaration ****************************/
2407 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
2408 : FuncDeclaration(loc, endloc,
2409 Identifier::generateId("_staticCtor"), STCstatic, NULL)
2413 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
2415 StaticCtorDeclaration *scd;
2417 assert(!s);
2418 scd = new StaticCtorDeclaration(loc, endloc);
2419 return FuncDeclaration::syntaxCopy(scd);
2423 void StaticCtorDeclaration::semantic(Scope *sc)
2425 //printf("StaticCtorDeclaration::semantic()\n");
2427 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2429 FuncDeclaration::semantic(sc);
2431 // We're going to need ModuleInfo
2432 Module *m = getModule();
2433 if (!m)
2434 m = sc->module;
2435 if (m)
2436 { m->needmoduleinfo = 1;
2437 #ifdef IN_GCC
2438 m->strictlyneedmoduleinfo = 1;
2439 #endif
2443 AggregateDeclaration *StaticCtorDeclaration::isThis()
2445 return NULL;
2448 int StaticCtorDeclaration::isStaticConstructor()
2450 return TRUE;
2453 int StaticCtorDeclaration::isVirtual()
2455 return FALSE;
2458 int StaticCtorDeclaration::addPreInvariant()
2460 return FALSE;
2463 int StaticCtorDeclaration::addPostInvariant()
2465 return FALSE;
2468 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2470 if (hgs->hdrgen)
2471 { buf->writestring("static this();\n");
2472 return;
2474 buf->writestring("static this()");
2475 bodyToCBuffer(buf, hgs);
2478 /********************************* StaticDtorDeclaration ****************************/
2480 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
2481 : FuncDeclaration(loc, endloc,
2482 Identifier::generateId("_staticDtor"), STCstatic, NULL)
2486 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
2488 StaticDtorDeclaration *sdd;
2490 assert(!s);
2491 sdd = new StaticDtorDeclaration(loc, endloc);
2492 return FuncDeclaration::syntaxCopy(sdd);
2496 void StaticDtorDeclaration::semantic(Scope *sc)
2498 ClassDeclaration *cd;
2499 Type *tret;
2501 cd = sc->scopesym->isClassDeclaration();
2502 if (!cd)
2505 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2507 FuncDeclaration::semantic(sc);
2509 // We're going to need ModuleInfo
2510 Module *m = getModule();
2511 if (!m)
2512 m = sc->module;
2513 if (m)
2514 { m->needmoduleinfo = 1;
2515 #ifdef IN_GCC
2516 m->strictlyneedmoduleinfo = 1;
2517 #endif
2521 AggregateDeclaration *StaticDtorDeclaration::isThis()
2523 return NULL;
2526 int StaticDtorDeclaration::isStaticDestructor()
2528 return TRUE;
2531 int StaticDtorDeclaration::isVirtual()
2533 return FALSE;
2536 int StaticDtorDeclaration::addPreInvariant()
2538 return FALSE;
2541 int StaticDtorDeclaration::addPostInvariant()
2543 return FALSE;
2546 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2548 if (hgs->hdrgen)
2549 return;
2550 buf->writestring("static ~this()");
2551 bodyToCBuffer(buf, hgs);
2554 /********************************* InvariantDeclaration ****************************/
2556 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
2557 : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
2561 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
2563 InvariantDeclaration *id;
2565 assert(!s);
2566 id = new InvariantDeclaration(loc, endloc);
2567 FuncDeclaration::syntaxCopy(id);
2568 return id;
2572 void InvariantDeclaration::semantic(Scope *sc)
2574 AggregateDeclaration *ad;
2575 Type *tret;
2577 parent = sc->parent;
2578 Dsymbol *parent = toParent();
2579 ad = parent->isAggregateDeclaration();
2580 if (!ad)
2582 error("invariants only are for struct/union/class definitions");
2583 return;
2585 else if (ad->inv && ad->inv != this)
2587 error("more than one invariant for %s", ad->toChars());
2589 ad->inv = this;
2590 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2592 sc = sc->push();
2593 sc->stc &= ~STCstatic; // not a static invariant
2594 sc->incontract++;
2595 sc->linkage = LINKd;
2597 FuncDeclaration::semantic(sc);
2599 sc->pop();
2602 int InvariantDeclaration::isVirtual()
2604 return FALSE;
2607 int InvariantDeclaration::addPreInvariant()
2609 return FALSE;
2612 int InvariantDeclaration::addPostInvariant()
2614 return FALSE;
2617 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2619 if (hgs->hdrgen)
2620 return;
2621 buf->writestring("invariant");
2622 bodyToCBuffer(buf, hgs);
2626 /********************************* UnitTestDeclaration ****************************/
2628 /*******************************
2629 * Generate unique unittest function Id so we can have multiple
2630 * instances per module.
2633 static Identifier *unitTestId()
2635 static int n;
2636 char buffer[10 + sizeof(n)*3 + 1];
2638 sprintf(buffer,"__unittest%d", n);
2639 n++;
2640 return Lexer::idPool(buffer);
2643 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
2644 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
2648 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
2650 UnitTestDeclaration *utd;
2652 assert(!s);
2653 utd = new UnitTestDeclaration(loc, endloc);
2654 return FuncDeclaration::syntaxCopy(utd);
2658 void UnitTestDeclaration::semantic(Scope *sc)
2660 if (global.params.useUnitTests)
2662 Type *tret;
2664 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2665 FuncDeclaration::semantic(sc);
2668 // We're going to need ModuleInfo even if the unit tests are not
2669 // compiled in, because other modules may import this module and refer
2670 // to this ModuleInfo.
2671 Module *m = getModule();
2672 if (!m)
2673 m = sc->module;
2674 if (m)
2675 m->needmoduleinfo = 1;
2678 AggregateDeclaration *UnitTestDeclaration::isThis()
2680 return NULL;
2683 int UnitTestDeclaration::isVirtual()
2685 return FALSE;
2688 int UnitTestDeclaration::addPreInvariant()
2690 return FALSE;
2693 int UnitTestDeclaration::addPostInvariant()
2695 return FALSE;
2698 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2700 if (hgs->hdrgen)
2701 return;
2702 buf->writestring("unittest");
2703 bodyToCBuffer(buf, hgs);
2706 /********************************* NewDeclaration ****************************/
2708 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2709 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
2711 this->arguments = arguments;
2712 this->varargs = varargs;
2715 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
2717 NewDeclaration *f;
2719 f = new NewDeclaration(loc, endloc, NULL, varargs);
2721 FuncDeclaration::syntaxCopy(f);
2723 f->arguments = Argument::arraySyntaxCopy(arguments);
2725 return f;
2729 void NewDeclaration::semantic(Scope *sc)
2731 ClassDeclaration *cd;
2732 Type *tret;
2734 //printf("NewDeclaration::semantic()\n");
2736 parent = sc->parent;
2737 Dsymbol *parent = toParent();
2738 cd = parent->isClassDeclaration();
2739 if (!cd && !parent->isStructDeclaration())
2741 error("new allocators only are for class or struct definitions");
2743 tret = Type::tvoid->pointerTo();
2744 type = new TypeFunction(arguments, tret, varargs, LINKd);
2746 type = type->semantic(loc, sc);
2747 assert(type->ty == Tfunction);
2749 // Check that there is at least one argument of type uint
2750 TypeFunction *tf = (TypeFunction *)type;
2751 if (Argument::dim(tf->parameters) < 1)
2753 error("at least one argument of type uint expected");
2755 else
2757 Argument *a = Argument::getNth(tf->parameters, 0);
2758 if (!a->type->equals(Type::tuns32) &&
2759 (! global.params.isX86_64 || !a->type->equals(Type::tuns64)))
2760 error("first argument must be type uint, not %s", a->type->toChars());
2763 FuncDeclaration::semantic(sc);
2766 char *NewDeclaration::kind()
2768 return "allocator";
2771 int NewDeclaration::isVirtual()
2773 return FALSE;
2776 int NewDeclaration::addPreInvariant()
2778 return FALSE;
2781 int NewDeclaration::addPostInvariant()
2783 return FALSE;
2786 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2788 buf->writestring("new");
2789 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2790 bodyToCBuffer(buf, hgs);
2794 /********************************* DeleteDeclaration ****************************/
2796 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
2797 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
2799 this->arguments = arguments;
2802 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
2804 DeleteDeclaration *f;
2806 f = new DeleteDeclaration(loc, endloc, NULL);
2808 FuncDeclaration::syntaxCopy(f);
2810 f->arguments = Argument::arraySyntaxCopy(arguments);
2812 return f;
2816 void DeleteDeclaration::semantic(Scope *sc)
2818 ClassDeclaration *cd;
2820 //printf("DeleteDeclaration::semantic()\n");
2822 parent = sc->parent;
2823 Dsymbol *parent = toParent();
2824 cd = parent->isClassDeclaration();
2825 if (!cd && !parent->isStructDeclaration())
2827 error("new allocators only are for class or struct definitions");
2829 type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
2831 type = type->semantic(loc, sc);
2832 assert(type->ty == Tfunction);
2834 // Check that there is only one argument of type void*
2835 TypeFunction *tf = (TypeFunction *)type;
2836 if (Argument::dim(tf->parameters) != 1)
2838 error("one argument of type void* expected");
2840 else
2842 Argument *a = Argument::getNth(tf->parameters, 0);
2843 if (!a->type->equals(Type::tvoid->pointerTo()))
2844 error("one argument of type void* expected, not %s", a->type->toChars());
2847 FuncDeclaration::semantic(sc);
2850 char *DeleteDeclaration::kind()
2852 return "deallocator";
2855 int DeleteDeclaration::isDelete()
2857 return TRUE;
2860 int DeleteDeclaration::isVirtual()
2862 return FALSE;
2865 int DeleteDeclaration::addPreInvariant()
2867 return FALSE;
2870 int DeleteDeclaration::addPostInvariant()
2872 return FALSE;
2875 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2877 buf->writestring("delete");
2878 Argument::argsToCBuffer(buf, hgs, arguments, 0);
2879 bodyToCBuffer(buf, hgs);