Merged Delight changes to D1 into D2
[delight/core.git] / dmd2 / func.c
blobc12b8a964a24e89816fdde127109b310e06cf3f9
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 fes = NULL;
75 introducing = 0;
76 tintro = NULL;
77 inferRetType = (type && type->nextOf() == NULL);
78 scope = NULL;
79 hasReturnExp = 0;
80 nrvo_can = 1;
81 nrvo_var = NULL;
82 shidden = NULL;
83 builtin = BUILTINunknown;
84 tookAddressOf = 0;
87 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
89 FuncDeclaration *f;
91 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
92 if (s)
93 f = (FuncDeclaration *)s;
94 else
95 f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
96 f->outId = outId;
97 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
98 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
99 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
100 assert(!fthrows); // deprecated
101 return f;
105 // Do the semantic analysis on the external interface to the function.
107 void FuncDeclaration::semantic(Scope *sc)
108 { TypeFunction *f;
109 StructDeclaration *sd;
110 ClassDeclaration *cd;
111 InterfaceDeclaration *id;
113 #if 0
114 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
115 if (isFuncLiteralDeclaration())
116 printf("\tFuncLiteralDeclaration()\n");
117 printf("sc->parent = %s\n", sc->parent->toChars());
118 printf("type: %p, %s\n", type, type->toChars());
119 #endif
121 storage_class |= sc->stc;
122 //printf("function storage_class = x%x\n", storage_class);
124 if (!originalType)
125 originalType = type;
126 if (!type->deco && type->nextOf())
128 #if 1
129 /* Apply const and invariant storage class
130 * to the function type
132 type = type->semantic(loc, sc);
133 if (storage_class & STCinvariant)
134 { // Don't use toInvariant(), as that will do a merge()
135 type = type->makeInvariant();
136 type->deco = type->merge()->deco;
138 else if (storage_class & STCconst)
140 if (!type->isInvariant())
141 { // Don't use toConst(), as that will do a merge()
142 type = type->makeConst();
143 type->deco = type->merge()->deco;
146 #else
147 if (storage_class & (STCconst | STCinvariant))
149 /* Apply const and invariant storage class
150 * to the function's return type
152 Type *tn = type->nextOf();
153 if (storage_class & STCconst)
154 tn = tn->makeConst();
155 if (storage_class & STCinvariant)
156 tn = tn->makeInvariant();
157 ((TypeNext *)type)->next = tn;
160 type = type->semantic(loc, sc);
161 #endif
163 //type->print();
164 if (type->ty != Tfunction)
166 error("%s must be a function", toChars());
167 return;
169 f = (TypeFunction *)(type);
171 size_t nparams = Argument::dim(f->parameters);
173 linkage = sc->linkage;
174 // if (!parent)
176 //parent = sc->scopesym;
177 parent = sc->parent;
179 protection = sc->protection;
180 if (attributes)
181 attributes->append(sc->attributes);
182 else
183 attributes = sc->attributes;
184 Dsymbol *parent = toParent();
186 if (isAuto() || isScope())
187 error("functions cannot be scope or auto");
189 if (isAbstract() && !isVirtual())
190 error("non-virtual functions cannot be abstract");
192 if ((f->isConst() || f->isInvariant()) && !isThis())
193 error("without 'this' cannot be const/invariant");
195 if (isAbstract() && isFinal())
196 error("cannot be both final and abstract");
197 #if 0
198 if (isAbstract() && fbody)
199 error("abstract functions cannot have bodies");
200 #endif
202 #if 0
203 if (isStaticConstructor() || isStaticDestructor())
205 if (!isStatic() || type->nextOf()->ty != Tvoid)
206 error("static constructors / destructors must be static void");
207 if (f->arguments && f->arguments->dim)
208 error("static constructors / destructors must have empty parameter list");
209 // BUG: check for invalid storage classes
211 #endif
213 #ifdef IN_GCC
214 AggregateDeclaration *ad;
216 ad = parent->isAggregateDeclaration();
217 if (ad)
218 ad->methods.push(this);
219 #endif
220 sd = parent->isStructDeclaration();
221 if (sd)
223 // Verify no constructors, destructors, etc.
224 if (isCtorDeclaration()
225 //||isDtorDeclaration()
226 //|| isInvariantDeclaration()
227 //|| isUnitTestDeclaration()
230 error("special member functions not allowed for %ss", sd->kind());
233 #if 0
234 if (!sd->inv)
235 sd->inv = isInvariantDeclaration();
237 if (!sd->aggNew)
238 sd->aggNew = isNewDeclaration();
240 if (isDelete())
242 if (sd->aggDelete)
243 error("multiple delete's for struct %s", sd->toChars());
244 sd->aggDelete = (DeleteDeclaration *)(this);
246 #endif
249 id = parent->isInterfaceDeclaration();
250 if (id)
252 storage_class |= STCabstract;
254 if (isCtorDeclaration() ||
255 isPostBlitDeclaration() ||
256 isDtorDeclaration() ||
257 isInvariantDeclaration() ||
258 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
259 error("special function not allowed in interface %s", id->toChars());
260 if (fbody)
261 error("function body is not abstract in interface %s", id->toChars());
264 cd = parent->isClassDeclaration();
265 if (cd)
266 { int vi;
267 CtorDeclaration *ctor;
268 DtorDeclaration *dtor;
269 InvariantDeclaration *inv;
271 if (isCtorDeclaration())
273 // ctor = (CtorDeclaration *)this;
274 // if (!cd->ctor)
275 // cd->ctor = ctor;
276 return;
279 #if 0
280 dtor = isDtorDeclaration();
281 if (dtor)
283 if (cd->dtor)
284 error("multiple destructors for class %s", cd->toChars());
285 cd->dtor = dtor;
288 inv = isInvariantDeclaration();
289 if (inv)
291 cd->inv = inv;
294 if (isNewDeclaration())
296 if (!cd->aggNew)
297 cd->aggNew = (NewDeclaration *)(this);
300 if (isDelete())
302 if (cd->aggDelete)
303 error("multiple delete's for class %s", cd->toChars());
304 cd->aggDelete = (DeleteDeclaration *)(this);
306 #endif
308 if (storage_class & STCabstract)
309 cd->isabstract = 1;
311 // if static function, do not put in vtbl[]
312 if (!isVirtual())
314 //printf("\tnot virtual\n");
315 goto Ldone;
318 // Find index of existing function in vtbl[] to override
319 vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
320 switch (vi)
322 case -1:
323 /* Didn't find one, so
324 * This is an 'introducing' function which gets a new
325 * slot in the vtbl[].
328 // Verify this doesn't override previous final function
329 if (cd->baseClass)
330 { Dsymbol *s = cd->baseClass->search(loc, ident, 0);
331 if (s)
333 FuncDeclaration *f = s->isFuncDeclaration();
334 f = f->overloadExactMatch(type);
335 if (f && f->isFinal() && f->prot() != PROTprivate)
336 error("cannot override final function %s", f->toPrettyChars());
340 if (isFinal())
342 cd->vtblFinal.push(this);
344 else
346 // Append to end of vtbl[]
347 //printf("\tintroducing function\n");
348 introducing = 1;
349 vi = cd->vtbl.dim;
350 cd->vtbl.push(this);
351 vtblIndex = vi;
354 break;
356 case -2: // can't determine because of fwd refs
357 cd->sizeok = 2; // can't finish due to forward reference
358 return;
360 default:
361 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
362 // This function is covariant with fdv
363 if (fdv->isFinal())
364 error("cannot override final function %s", fdv->toPrettyChars());
366 if (!isOverride() && (global.params.warnings || sc->module->isDltFile))
367 error("overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
369 if (fdv->toParent() == parent)
371 // If both are mixins, then error.
372 // If either is not, the one that is not overrides
373 // the other.
374 if (fdv->parent->isClassDeclaration())
375 break;
376 if (!this->parent->isClassDeclaration()
377 #if !BREAKABI
378 && !isDtorDeclaration()
379 #endif
380 && !isPostBlitDeclaration()
382 error("multiple overrides of same function");
384 cd->vtbl.data[vi] = (void *)this;
385 vtblIndex = vi;
387 /* This works by whenever this function is called,
388 * it actually returns tintro, which gets dynamically
389 * cast to type. But we know that tintro is a base
390 * of type, so we could optimize it by not doing a
391 * dynamic cast, but just subtracting the isBaseOf()
392 * offset if the value is != null.
395 if (fdv->tintro)
396 tintro = fdv->tintro;
397 else if (!type->equals(fdv->type))
399 /* Only need to have a tintro if the vptr
400 * offsets differ
402 target_ptrdiff_t offset;
403 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
405 tintro = fdv->type;
408 break;
412 /* Go through all the interface bases.
413 * If this function is covariant with any members of those interface
414 * functions, set the tintro.
416 for (int i = 0; i < cd->interfaces_dim; i++)
418 BaseClass *b = cd->interfaces[i];
419 vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
420 switch (vi)
422 case -1:
423 break;
425 case -2:
426 cd->sizeok = 2; // can't finish due to forward reference
427 return;
429 default:
430 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
431 Type *ti = NULL;
433 if (fdv->tintro)
434 ti = fdv->tintro;
435 else if (!type->equals(fdv->type))
437 /* Only need to have a tintro if the vptr
438 * offsets differ
440 target_ptrdiff_t offset;
441 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
443 ti = fdv->type;
444 #if 0
445 if (offset)
446 ti = fdv->type;
447 else if (type->nextOf()->ty == Tclass)
448 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
449 if (cdn && cdn->sizeok != 1)
450 ti = fdv->type;
452 #endif
455 if (ti)
457 if (tintro && !tintro->equals(ti))
459 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
461 tintro = ti;
463 goto L2;
468 if (introducing && isOverride())
470 error("does not override any function");
473 L2: ;
475 else if (isOverride() && !parent->isTemplateInstance())
476 error("override only applies to class member functions");
478 /* Do not allow template instances to add virtual functions
479 * to a class.
481 if (isVirtual())
483 TemplateInstance *ti = parent->isTemplateInstance();
484 if (ti)
486 // Take care of nested templates
487 while (1)
489 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
490 if (!ti2)
491 break;
492 ti = ti2;
495 // If it's a member template
496 ClassDeclaration *cd = ti->tempdecl->isClassMember();
497 if (cd)
499 error("cannot use template to add virtual function to class '%s'", cd->toChars());
504 if (isMain())
506 // Check parameters to see if they are either () or (char[][] args)
507 switch (nparams)
509 case 0:
510 break;
512 case 1:
514 Argument *arg0 = Argument::getNth(f->parameters, 0);
515 if (arg0->type->ty != Tarray ||
516 arg0->type->nextOf()->ty != Tarray ||
517 arg0->type->nextOf()->nextOf()->ty != Tchar ||
518 arg0->storageClass & (STCout | STCref | STClazy))
519 goto Lmainerr;
520 break;
523 default:
524 goto Lmainerr;
527 if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
528 error("must return int or void, not %s", f->nextOf()->toChars());
529 if (f->varargs)
531 Lmainerr:
532 error("parameters must be main() or main(char[][] args)");
536 if (ident == Id::assign && (sd || cd))
537 { // Disallow identity assignment operator.
539 // opAssign(...)
540 if (nparams == 0)
541 { if (f->varargs == 1)
542 goto Lassignerr;
544 else
546 Argument *arg0 = Argument::getNth(f->parameters, 0);
547 Type *t0 = arg0->type->toBasetype();
548 Type *tb = sd ? sd->type : cd->type;
549 if (arg0->type->implicitConvTo(tb) ||
550 (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
553 if (nparams == 1)
554 goto Lassignerr;
555 Argument *arg1 = Argument::getNth(f->parameters, 1);
556 if (arg1->defaultArg)
557 goto Lassignerr;
562 Ldone:
563 /* Save scope for possible later use (if we need the
564 * function internals)
566 scope = new Scope(*sc);
567 scope->setNoFree();
568 return;
570 Lassignerr:
571 if (sd)
573 sd->hasIdentityAssign = 1; // don't need to generate it
574 goto Ldone;
576 error("identity assignment operator overload is illegal");
579 void FuncDeclaration::semantic2(Scope *sc)
583 // Do the semantic analysis on the internals of the function.
585 void FuncDeclaration::semantic3(Scope *sc)
586 { TypeFunction *f;
587 AggregateDeclaration *ad;
588 VarDeclaration *argptr = NULL;
589 VarDeclaration *_arguments = NULL;
591 if (!parent)
593 if (global.errors)
594 return;
595 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
596 assert(0);
598 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
599 //fflush(stdout);
600 //{ static int x; if (++x == 2) *(char*)0=0; }
601 //printf("\tlinkage = %d\n", sc->linkage);
603 //printf(" sc->incontract = %d\n", sc->incontract);
604 if (semanticRun)
605 return;
606 semanticRun = 1;
608 if (!type || type->ty != Tfunction)
609 return;
610 f = (TypeFunction *)(type);
612 // Check the 'throws' clause
613 if (fthrows)
614 { int i;
616 for (i = 0; i < fthrows->dim; i++)
618 Type *t = (Type *)fthrows->data[i];
620 t = t->semantic(loc, sc);
621 if (!t->isClassHandle())
622 error("can only throw classes, not %s", t->toChars());
626 if (fbody || frequire)
628 /* Symbol table into which we place parameters and nested functions,
629 * solely to diagnose name collisions.
631 localsymtab = new DsymbolTable();
633 // Establish function scope
634 ScopeDsymbol *ss = new ScopeDsymbol();
635 ss->parent = sc->scopesym;
636 Scope *sc2 = sc->push(ss);
637 sc2->func = this;
638 sc2->parent = this;
639 sc2->callSuper = 0;
640 sc2->sbreak = NULL;
641 sc2->scontinue = NULL;
642 sc2->sw = NULL;
643 sc2->fes = fes;
644 sc2->linkage = LINKd;
645 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCconst | STCfinal | STCinvariant | STCtls);
646 sc2->attributes = NULL;
647 sc2->protection = PROTpublic;
648 sc2->explicitProtection = 0;
649 sc2->structalign = 8;
650 sc2->incontract = 0;
651 sc2->tf = NULL;
652 sc2->noctor = 0;
654 // Declare 'this'
655 ad = isThis();
656 if (ad)
657 { VarDeclaration *v;
659 if (isFuncLiteralDeclaration() && isNested())
661 error("literals cannot be class members");
662 return;
664 else
666 assert(!isNested()); // can't be both member and nested
667 assert(ad->handle);
668 Type *thandle = ad->handle;
669 if (storage_class & STCconst || type->isConst())
671 if (thandle->ty == Tclass)
672 thandle = thandle->constOf();
673 else
674 { assert(thandle->ty == Tpointer);
675 thandle = thandle->nextOf()->constOf()->pointerTo();
678 else if (storage_class & STCinvariant || type->isInvariant())
680 if (thandle->ty == Tclass)
681 thandle = thandle->invariantOf();
682 else
683 { assert(thandle->ty == Tpointer);
684 thandle = thandle->nextOf()->invariantOf()->pointerTo();
687 v = new ThisDeclaration(thandle);
688 v->storage_class |= STCparameter;
689 v->semantic(sc2);
690 if (!sc2->insert(v))
691 assert(0);
692 v->parent = this;
693 vthis = v;
696 else if (isNested())
698 /* The 'this' for a nested function is the link to the
699 * enclosing function's stack frame.
700 * Note that nested functions and member functions are disjoint.
702 VarDeclaration *v = new ThisDeclaration(Type::tvoid->pointerTo());
703 v->storage_class |= STCparameter;
704 v->semantic(sc2);
705 if (!sc2->insert(v))
706 assert(0);
707 v->parent = this;
708 vthis = v;
711 // Declare hidden variable _arguments[] and _argptr
712 if (f->varargs == 1)
713 { Type *t;
715 if (f->linkage == LINKd)
716 { // Declare _arguments[]
717 #if BREAKABI
718 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
719 v_arguments->storage_class = STCparameter;
720 v_arguments->semantic(sc2);
721 sc2->insert(v_arguments);
722 v_arguments->parent = this;
724 //t = Type::typeinfo->type->constOf()->arrayOf();
725 t = Type::typeinfo->type->arrayOf();
726 _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
727 _arguments->skipnullcheck = TRUE;
728 _arguments->semantic(sc2);
729 sc2->insert(_arguments);
730 _arguments->parent = this;
731 #else
732 t = Type::typeinfo->type->arrayOf();
733 v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
734 v_arguments->storage_class = STCparameter | STCin;
735 v_arguments->semantic(sc2);
736 sc2->insert(v_arguments);
737 v_arguments->parent = this;
738 #endif
740 if (f->linkage == LINKd || (parameters && parameters->dim))
741 { // Declare _argptr
742 #if IN_GCC
743 t = d_gcc_builtin_va_list_d_type;
744 #else
745 t = Type::tvoid->pointerTo();
746 #endif
747 argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
748 argptr->skipnullcheck = TRUE;
749 argptr->semantic(sc2);
750 sc2->insert(argptr);
751 argptr->parent = this;
755 // Propagate storage class from tuple parameters to their element-parameters.
756 if (f->parameters)
758 for (size_t i = 0; i < f->parameters->dim; i++)
759 { Argument *arg = (Argument *)f->parameters->data[i];
761 if (arg->type->ty == Ttuple)
762 { TypeTuple *t = (TypeTuple *)arg->type;
763 size_t dim = Argument::dim(t->arguments);
764 for (size_t j = 0; j < dim; j++)
765 { Argument *narg = Argument::getNth(t->arguments, j);
766 narg->storageClass = arg->storageClass;
772 /* Declare all the function parameters as variables
773 * and install them in parameters[]
775 size_t nparams = Argument::dim(f->parameters);
776 if (nparams)
777 { /* parameters[] has all the tuples removed, as the back end
778 * doesn't know about tuples
780 parameters = new Dsymbols();
781 parameters->reserve(nparams);
782 for (size_t i = 0; i < nparams; i++)
784 Argument *arg = Argument::getNth(f->parameters, i);
785 Identifier *id = arg->ident;
786 if (!id)
788 /* Generate identifier for un-named parameter,
789 * because we need it later on.
791 OutBuffer buf;
792 buf.printf("_param_%"PRIuSIZE, i);
793 char *name = (char *)buf.extractData();
794 id = new Identifier(name, TOKidentifier);
795 arg->ident = id;
797 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
798 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
799 v->storage_class |= STCparameter;
800 if (f->varargs == 2 && i + 1 == nparams)
801 v->storage_class |= STCvariadic;
802 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STCconst | STCinvariant | STCnodtor);
803 v->semantic(sc2);
804 if (!sc2->insert(v))
805 error("parameter %s.%s is already defined", toChars(), v->toChars());
806 else
807 parameters->push(v);
808 localsymtab->insert(v);
809 v->parent = this;
813 // Declare the tuple symbols and put them in the symbol table,
814 // but not in parameters[].
815 if (f->parameters)
817 for (size_t i = 0; i < f->parameters->dim; i++)
818 { Argument *arg = (Argument *)f->parameters->data[i];
820 if (!arg->ident)
821 continue; // never used, so ignore
822 if (arg->type->ty == Ttuple)
823 { TypeTuple *t = (TypeTuple *)arg->type;
824 size_t dim = Argument::dim(t->arguments);
825 Objects *exps = new Objects();
826 exps->setDim(dim);
827 for (size_t j = 0; j < dim; j++)
828 { Argument *narg = Argument::getNth(t->arguments, j);
829 assert(narg->ident);
830 VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
831 assert(v);
832 Expression *e = new VarExp(v->loc, v);
833 exps->data[j] = (void *)e;
835 assert(arg->ident);
836 TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
837 //printf("declaring tuple %s\n", v->toChars());
838 v->isexp = 1;
839 if (!sc2->insert(v))
840 error("parameter %s.%s is already defined", toChars(), v->toChars());
841 localsymtab->insert(v);
842 v->parent = this;
847 /* Do the semantic analysis on the [in] preconditions and
848 * [out] postconditions.
850 sc2->incontract++;
852 if (frequire)
853 { /* frequire is composed of the [in] contracts
855 // BUG: need to error if accessing out parameters
856 // BUG: need to treat parameters as const
857 // BUG: need to disallow returns and throws
858 // BUG: verify that all in and ref parameters are read
859 frequire = frequire->semantic(sc2);
860 labtab = NULL; // so body can't refer to labels
863 if (fensure || addPostInvariant())
864 { /* fensure is composed of the [out] contracts
866 ScopeDsymbol *sym = new ScopeDsymbol();
867 sym->parent = sc2->scopesym;
868 sc2 = sc2->push(sym);
870 assert(type->nextOf());
871 if (type->nextOf()->ty == Tvoid)
873 if (outId)
874 error("void functions have no result");
876 else
878 if (!outId)
879 outId = Id::result; // provide a default
882 if (outId)
883 { // Declare result variable
884 VarDeclaration *v;
885 Loc loc = this->loc;
887 if (fensure)
888 loc = fensure->loc;
890 v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
891 v->noauto = 1;
892 v->skipnullcheck = 1;
893 sc2->incontract--;
894 v->semantic(sc2);
895 sc2->incontract++;
896 if (!sc2->insert(v))
897 error("out result %s is already defined", v->toChars());
898 v->parent = this;
899 vresult = v;
901 // vresult gets initialized with the function return value
902 // in ReturnStatement::semantic()
905 // BUG: need to treat parameters as const
906 // BUG: need to disallow returns and throws
907 if (fensure)
908 { fensure = fensure->semantic(sc2);
909 labtab = NULL; // so body can't refer to labels
912 if (!global.params.useOut)
913 { fensure = NULL; // discard
914 vresult = NULL;
917 // Postcondition invariant
918 if (addPostInvariant())
920 Expression *e = NULL;
921 if (isCtorDeclaration())
923 // Call invariant directly only if it exists
924 InvariantDeclaration *inv = ad->inv;
925 ClassDeclaration *cd = ad->isClassDeclaration();
927 while (!inv && cd)
929 cd = cd->baseClass;
930 if (!cd)
931 break;
932 inv = cd->inv;
934 if (inv)
936 e = new DsymbolExp(0, inv);
937 e = new CallExp(0, e);
938 e = e->semantic(sc2);
941 else
942 { // Call invariant virtually
943 ThisExp *v = new ThisExp(0);
944 v->type = vthis->type;
945 e = new AssertExp(0, v);
947 if (e)
949 ExpStatement *s = new ExpStatement(0, e);
950 if (fensure)
951 fensure = new CompoundStatement(0, s, fensure);
952 else
953 fensure = s;
957 if (fensure)
958 { returnLabel = new LabelDsymbol(Id::returnLabel);
959 LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
960 ls->isReturnLabel = 1;
961 returnLabel->statement = ls;
963 sc2 = sc2->pop();
966 sc2->incontract--;
968 if (fbody)
969 { ClassDeclaration *cd = isClassMember();
971 /* If this is a class constructor
973 if (isCtorDeclaration() && cd)
975 for (int i = 0; i < cd->fields.dim; i++)
976 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
978 v->ctorinit = 0;
982 if (inferRetType || f->retStyle() != RETstack)
983 nrvo_can = 0;
985 fbody = fbody->semantic(sc2);
987 if (inferRetType)
988 { // If no return type inferred yet, then infer a void
989 if (!type->nextOf())
991 ((TypeFunction *)type)->next = Type::tvoid;
992 type = type->semantic(loc, sc);
994 f = (TypeFunction *)type;
997 if (isStaticCtorDeclaration())
998 { /* It's a static constructor. Ensure that all
999 * ctor consts were initialized.
1002 Dsymbol *p = toParent();
1003 ScopeDsymbol *ad = p->isScopeDsymbol();
1004 if (!ad)
1006 error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
1008 else
1010 for (int i = 0; i < ad->members->dim; i++)
1011 { Dsymbol *s = (Dsymbol *)ad->members->data[i];
1013 s->checkCtorConstInit();
1018 if (isCtorDeclaration() && cd)
1020 //printf("callSuper = x%x\n", sc2->callSuper);
1022 // Verify that all the ctorinit fields got initialized
1023 // Also check that non-null members got set
1024 if (!(sc2->callSuper & CSXthis_ctor))
1026 for (int i = 0; i < cd->fields.dim; i++)
1027 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
1029 if (v->ctorinit == 0)
1031 if (v->isCtorinit())
1032 error("missing initializer for final field %s", v->toChars());
1033 else if (!v->skipnullcheck &&
1034 (v->type->ty == Tclass || v->type->ty == Tpointer))
1035 error("missing initializer for non-null field %s", v->toChars());
1040 if (!(sc2->callSuper & CSXany_ctor) &&
1041 cd->baseClass && cd->baseClass->ctor)
1043 sc2->callSuper = 0;
1045 // Insert implicit super() at start of fbody
1046 Expression *e1 = new SuperExp(0);
1047 Expression *e = new CallExp(0, e1);
1049 unsigned errors = global.errors;
1050 global.gag++;
1051 e = e->semantic(sc2);
1052 global.gag--;
1053 if (errors != global.errors)
1054 error("no match for implicit super() call in constructor");
1056 Statement *s = new ExpStatement(0, e);
1057 fbody = new CompoundStatement(0, s, fbody);
1060 else if (fes)
1061 { // For foreach(){} body, append a return 0;
1062 Expression *e = new IntegerExp(0);
1063 Statement *s = new ReturnStatement(0, e);
1064 fbody = new CompoundStatement(0, fbody, s);
1065 assert(!returnLabel);
1067 else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1068 error("expected to return a value of type %s", type->nextOf()->toChars());
1069 else if (!inlineAsm)
1071 int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
1072 //int offend = fbody ? fbody->fallOffEnd() : TRUE;
1074 if (type->nextOf()->ty == Tvoid)
1076 if (offend && isMain())
1077 { // Add a return 0; statement
1078 Statement *s = new ReturnStatement(0, new IntegerExp(0));
1079 fbody = new CompoundStatement(0, fbody, s);
1082 else
1084 if (offend)
1085 { Expression *e;
1087 if (global.params.warnings)
1088 { fprintf(stdmsg, "warning - ");
1089 error("no return at end of function");
1092 if (global.params.useAssert &&
1093 !global.params.useInline)
1094 { /* Add an assert(0, msg); where the missing return
1095 * should be.
1097 e = new AssertExp(
1098 endloc,
1099 new IntegerExp(0),
1100 new StringExp(loc, "missing return expression")
1103 else
1104 e = new HaltExp(endloc);
1105 e = new CommaExp(0, e, type->nextOf()->defaultInit());
1106 e = e->semantic(sc2);
1107 Statement *s = new ExpStatement(0, e);
1108 fbody = new CompoundStatement(0, fbody, s);
1115 Statements *a = new Statements();
1117 // Merge in initialization of 'out' parameters
1118 if (parameters)
1119 { for (size_t i = 0; i < parameters->dim; i++)
1121 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1122 if (v->storage_class & STCout)
1124 assert(v->init);
1125 ExpInitializer *ie = v->init->isExpInitializer();
1126 assert(ie);
1127 a->push(new ExpStatement(0, ie->exp));
1132 if (argptr)
1133 { // Initialize _argptr to point past non-variadic arg
1134 #if IN_GCC
1135 // Handled in FuncDeclaration::toObjFile
1136 v_argptr = argptr;
1137 v_argptr->init = new VoidInitializer(loc);
1138 #else
1139 Expression *e1;
1140 Expression *e;
1141 Type *t = argptr->type;
1142 VarDeclaration *p;
1143 unsigned offset;
1145 e1 = new VarExp(0, argptr);
1146 if (parameters && parameters->dim)
1147 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1148 else
1149 p = v_arguments; // last parameter is _arguments[]
1150 offset = p->type->size();
1151 offset = (offset + 3) & ~3; // assume stack aligns on 4
1152 e = new SymOffExp(0, p, offset);
1153 e = new AssignExp(0, e1, e);
1154 e->type = t;
1155 a->push(new ExpStatement(0, e));
1156 #endif
1159 if (_arguments)
1161 #if IN_GCC
1162 v_arguments_var = _arguments;
1163 v_arguments_var->init = new VoidInitializer(loc);
1164 #endif
1165 /* Advance to elements[] member of TypeInfo_Tuple with:
1166 * _arguments = v_arguments.elements;
1168 Expression *e = new VarExp(0, v_arguments);
1169 e = new DotIdExp(0, e, Id::elements);
1170 Expression *e1 = new VarExp(0, _arguments);
1171 e = new AssignExp(0, e1, e);
1172 e->op = TOKconstruct;
1173 e = e->semantic(sc);
1174 a->push(new ExpStatement(0, e));
1177 // Merge contracts together with body into one compound statement
1179 #ifdef _DH
1180 if (frequire && global.params.useIn)
1181 { frequire->incontract = 1;
1182 a->push(frequire);
1184 #else
1185 if (frequire && global.params.useIn)
1186 a->push(frequire);
1187 #endif
1189 // Precondition invariant
1190 if (addPreInvariant())
1192 Expression *e = NULL;
1193 if (isDtorDeclaration())
1195 // Call invariant directly only if it exists
1196 InvariantDeclaration *inv = ad->inv;
1197 ClassDeclaration *cd = ad->isClassDeclaration();
1199 while (!inv && cd)
1201 cd = cd->baseClass;
1202 if (!cd)
1203 break;
1204 inv = cd->inv;
1206 if (inv)
1208 e = new DsymbolExp(0, inv);
1209 e = new CallExp(0, e);
1210 e = e->semantic(sc2);
1213 else
1214 { // Call invariant virtually
1215 ThisExp *v = new ThisExp(0);
1216 v->type = vthis->type;
1217 Expression *se = new StringExp(0, "null this");
1218 se = se->semantic(sc);
1219 se->type = Type::tchar->arrayOf();
1220 e = new AssertExp(loc, v, se);
1222 if (e)
1224 ExpStatement *s = new ExpStatement(0, e);
1225 a->push(s);
1229 if (fbody)
1230 a->push(fbody);
1232 if (fensure)
1234 a->push(returnLabel->statement);
1236 if (type->nextOf()->ty != Tvoid)
1238 // Create: return vresult;
1239 assert(vresult);
1240 Expression *e = new VarExp(0, vresult);
1241 if (tintro)
1242 { e = e->implicitCastTo(sc, tintro->nextOf());
1243 e = e->semantic(sc);
1245 ReturnStatement *s = new ReturnStatement(0, e);
1246 a->push(s);
1250 fbody = new CompoundStatement(0, a);
1252 /* Append destructor calls for parameters as finally blocks.
1254 if (parameters)
1255 { for (size_t i = 0; i < parameters->dim; i++)
1257 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1259 if (v->storage_class & (STCref | STCout))
1260 continue;
1262 /* Don't do this for static arrays, since static
1263 * arrays are called by reference. Remove this
1264 * when we change them to call by value.
1266 if (v->type->toBasetype()->ty == Tsarray)
1267 continue;
1269 Expression *e = v->callAutoDtor(sc);
1270 if (e)
1271 { Statement *s = new ExpStatement(0, e);
1272 s = s->semantic(sc);
1273 if (fbody->blockExit() == BEfallthru)
1274 fbody = new CompoundStatement(0, fbody, s);
1275 else
1276 fbody = new TryFinallyStatement(0, fbody, s);
1282 sc2->callSuper = 0;
1283 sc2->pop();
1285 semanticRun = 2;
1288 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1290 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1292 type->toCBuffer(buf, ident, hgs);
1293 bodyToCBuffer(buf, hgs);
1297 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1299 if (fbody &&
1300 (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1302 { buf->writenl();
1304 // in{}
1305 if (frequire)
1306 { buf->writestring("in");
1307 buf->writenl();
1308 frequire->toCBuffer(buf, hgs);
1311 // out{}
1312 if (fensure)
1313 { buf->writestring("out");
1314 if (outId)
1315 { buf->writebyte('(');
1316 buf->writestring(outId->toChars());
1317 buf->writebyte(')');
1319 buf->writenl();
1320 fensure->toCBuffer(buf, hgs);
1323 if (frequire || fensure)
1324 { buf->writestring("body");
1325 buf->writenl();
1328 buf->writebyte('{');
1329 buf->writenl();
1330 fbody->toCBuffer(buf, hgs);
1331 buf->writebyte('}');
1332 buf->writenl();
1334 else
1335 { buf->writeByte(';');
1336 buf->writenl();
1340 /****************************************************
1341 * Determine if 'this' overrides fd.
1342 * Return !=0 if it does.
1345 int FuncDeclaration::overrides(FuncDeclaration *fd)
1346 { int result = 0;
1348 if (fd->ident == ident)
1350 int cov = type->covariant(fd->type);
1351 if (cov)
1352 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1353 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1355 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1356 result = 1;
1359 return result;
1362 /*************************************************
1363 * Find index of function in vtbl[0..dim] that
1364 * this function overrides.
1365 * Returns:
1366 * -1 didn't find one
1367 * -2 can't determine because of forward references
1370 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
1372 for (int vi = 0; vi < dim; vi++)
1374 FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
1375 if (fdv && fdv->ident == ident)
1377 int cov = type->covariant(fdv->type);
1378 //printf("\tbaseclass cov = %d\n", cov);
1379 switch (cov)
1381 case 0: // types are distinct
1382 break;
1384 case 1:
1385 return vi;
1387 case 2:
1388 //type->print();
1389 //fdv->type->print();
1390 //printf("%s %s\n", type->deco, fdv->type->deco);
1391 error("of type %s overrides but is not covariant with %s of type %s",
1392 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
1393 break;
1395 case 3:
1396 return -2; // forward references
1398 default:
1399 assert(0);
1403 return -1;
1406 /****************************************************
1407 * Overload this FuncDeclaration with the new one f.
1408 * Return !=0 if successful; i.e. no conflict.
1411 int FuncDeclaration::overloadInsert(Dsymbol *s)
1413 FuncDeclaration *f;
1414 AliasDeclaration *a;
1416 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1417 a = s->isAliasDeclaration();
1418 if (a)
1420 if (overnext)
1421 return overnext->overloadInsert(a);
1422 if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1424 //printf("\ta = '%s'\n", a->type->toChars());
1425 return FALSE;
1427 overnext = a;
1428 //printf("\ttrue: no conflict\n");
1429 return TRUE;
1431 f = s->isFuncDeclaration();
1432 if (!f)
1433 return FALSE;
1435 #if 0
1436 /* Disable this check because:
1437 * const void foo();
1438 * semantic() isn't run yet on foo(), so the const hasn't been
1439 * applied yet.
1441 if (type)
1442 { printf("type = %s\n", type->toChars());
1443 printf("f->type = %s\n", f->type->toChars());
1445 if (type && f->type && // can be NULL for overloaded constructors
1446 f->type->covariant(type) &&
1447 f->type->mod == type->mod &&
1448 !isFuncAliasDeclaration())
1450 //printf("\tfalse: conflict %s\n", kind());
1451 return FALSE;
1453 #endif
1455 if (overnext)
1456 return overnext->overloadInsert(f);
1457 overnext = f;
1458 //printf("\ttrue: no conflict\n");
1459 return TRUE;
1462 /***************************************************
1463 * Visit each overloaded function in turn, and call
1464 * (*fp)(param, f) on it.
1465 * Exit when no more, or (*fp)(param, f) returns 1.
1466 * Returns:
1467 * 0 continue
1468 * 1 done
1471 int overloadApply(FuncDeclaration *fstart,
1472 int (*fp)(void *, FuncDeclaration *),
1473 void *param)
1475 FuncDeclaration *f;
1476 Declaration *d;
1477 Declaration *next;
1479 for (d = fstart; d; d = next)
1480 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1482 if (fa)
1484 if (overloadApply(fa->funcalias, fp, param))
1485 return 1;
1486 next = fa->overnext;
1488 else
1490 AliasDeclaration *a = d->isAliasDeclaration();
1492 if (a)
1494 Dsymbol *s = a->toAlias();
1495 next = s->isDeclaration();
1496 if (next == a)
1497 break;
1498 if (next == fstart)
1499 break;
1501 else
1503 f = d->isFuncDeclaration();
1504 if (!f)
1505 { d->error("is aliased to a function");
1506 break; // BUG: should print error message?
1508 if ((*fp)(param, f))
1509 return 1;
1511 next = f->overnext;
1515 return 0;
1518 /********************************************
1519 * If there are no overloads of function f, return that function,
1520 * otherwise return NULL.
1523 static int fpunique(void *param, FuncDeclaration *f)
1524 { FuncDeclaration **pf = (FuncDeclaration **)param;
1526 if (*pf)
1527 { *pf = NULL;
1528 return 1; // ambiguous, done
1530 else
1531 { *pf = f;
1532 return 0;
1536 FuncDeclaration *FuncDeclaration::isUnique()
1537 { FuncDeclaration *result = NULL;
1539 overloadApply(this, &fpunique, &result);
1540 return result;
1543 /********************************************
1544 * Find function in overload list that exactly matches t.
1547 struct Param1
1549 Type *t; // type to match
1550 FuncDeclaration *f; // return value
1553 int fp1(void *param, FuncDeclaration *f)
1554 { Param1 *p = (Param1 *)param;
1555 Type *t = p->t;
1557 if (t->equals(f->type))
1558 { p->f = f;
1559 return 1;
1562 #if V2
1563 /* Allow covariant matches, if it's just a const conversion
1564 * of the return type
1566 if (t->ty == Tfunction)
1567 { TypeFunction *tf = (TypeFunction *)f->type;
1568 if (tf->covariant(t) == 1 &&
1569 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
1571 p->f = f;
1572 return 1;
1575 #endif
1576 return 0;
1579 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1581 Param1 p;
1582 p.t = t;
1583 p.f = NULL;
1584 overloadApply(this, &fp1, &p);
1585 return p.f;
1589 /********************************************
1590 * Decide which function matches the arguments best.
1593 struct Param2
1595 Match *m;
1596 Expression *ethis;
1597 Expressions *arguments;
1600 int fp2(void *param, FuncDeclaration *f)
1601 { Param2 *p = (Param2 *)param;
1602 Match *m = p->m;
1603 Expressions *arguments = p->arguments;
1604 MATCH match;
1606 if (f != m->lastf) // skip duplicates
1608 m->anyf = f;
1609 TypeFunction *tf = (TypeFunction *)f->type;
1610 match = (MATCH) tf->callMatch(f->needThis() ? p->ethis : NULL, arguments);
1611 //printf("match = %d\n", match);
1612 if (match != MATCHnomatch)
1614 if (match > m->last)
1615 goto LfIsBetter;
1617 if (match < m->last)
1618 goto LlastIsBetter;
1620 /* See if one of the matches overrides the other.
1622 if (m->lastf->overrides(f))
1623 goto LlastIsBetter;
1624 else if (f->overrides(m->lastf))
1625 goto LfIsBetter;
1627 /* Try to disambiguate using template-style partial ordering rules.
1628 * In essence, if f() and g() are ambiguous, if f() can call g(),
1629 * but g() cannot call f(), then pick f().
1630 * This is because f() is "more specialized."
1633 MATCH c1 = f->leastAsSpecialized(m->lastf);
1634 MATCH c2 = m->lastf->leastAsSpecialized(f);
1635 if (c1 > c2)
1636 goto LfIsBetter;
1637 if (c1 < c2)
1638 goto LlastIsBetter;
1641 Lambiguous:
1642 m->nextf = f;
1643 m->count++;
1644 return 0;
1646 LfIsBetter:
1647 m->last = match;
1648 m->lastf = f;
1649 m->count = 1;
1650 return 0;
1652 LlastIsBetter:
1653 return 0;
1656 return 0;
1659 void overloadResolveX(Match *m, FuncDeclaration *fstart,
1660 Expression *ethis, Expressions *arguments)
1662 Param2 p;
1663 p.m = m;
1664 p.ethis = ethis;
1665 p.arguments = arguments;
1666 overloadApply(fstart, &fp2, &p);
1670 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags)
1672 TypeFunction *tf;
1673 Match m;
1675 #if 0
1676 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1677 if (arguments)
1678 { int i;
1680 for (i = 0; i < arguments->dim; i++)
1681 { Expression *arg;
1683 arg = (Expression *)arguments->data[i];
1684 assert(arg->type);
1685 printf("\t%s: ", arg->toChars());
1686 arg->type->print();
1689 #endif
1691 memset(&m, 0, sizeof(m));
1692 m.last = MATCHnomatch;
1693 overloadResolveX(&m, this, ethis, arguments);
1695 if (m.count == 1) // exactly one match
1697 return m.lastf;
1699 else
1701 OutBuffer buf;
1703 if (arguments)
1705 HdrGenState hgs;
1707 argExpTypesToCBuffer(&buf, arguments, &hgs);
1710 if (m.last == MATCHnomatch)
1712 if (flags & 1) // if do not print error messages
1713 return NULL; // no match
1715 tf = (TypeFunction *)type;
1717 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1718 error(loc, "%s does not match parameter types (%s)",
1719 Argument::argsTypesToChars(tf->parameters, tf->varargs),
1720 buf.toChars());
1721 return m.anyf; // as long as it's not a FuncAliasDeclaration
1723 else
1725 #if 1
1726 TypeFunction *t1 = (TypeFunction *)m.lastf->type;
1727 TypeFunction *t2 = (TypeFunction *)m.nextf->type;
1729 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1730 buf.toChars(),
1731 m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
1732 m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
1733 #else
1734 error(loc, "overloads %s and %s both match argument list for %s",
1735 m.lastf->type->toChars(),
1736 m.nextf->type->toChars(),
1737 m.lastf->toChars());
1738 #endif
1739 return m.lastf;
1744 /*************************************
1745 * Determine partial specialization order of 'this' vs g.
1746 * This is very similar to TemplateDeclaration::leastAsSpecialized().
1747 * Returns:
1748 * match 'this' is at least as specialized as g
1749 * 0 g is more specialized than 'this'
1752 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
1754 #define LOG_LEASTAS 0
1756 #if LOG_LEASTAS
1757 printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
1758 #endif
1760 /* This works by calling g() with f()'s parameters, and
1761 * if that is possible, then f() is at least as specialized
1762 * as g() is.
1765 TypeFunction *tf = (TypeFunction *)type;
1766 TypeFunction *tg = (TypeFunction *)g->type;
1767 size_t nfparams = Argument::dim(tf->parameters);
1768 size_t ngparams = Argument::dim(tg->parameters);
1769 MATCH match = MATCHexact;
1771 /* If both functions have a 'this' pointer, and the mods are not
1772 * the same and g's is not const, then this is less specialized.
1774 if (needThis() && g->needThis())
1776 if (tf->mod != tg->mod)
1778 if (tg->mod == MODconst)
1779 match = MATCHconst;
1780 else
1781 return MATCHnomatch;
1785 /* Create a dummy array of arguments out of the parameters to f()
1787 Expressions args;
1788 args.setDim(nfparams);
1789 for (int u = 0; u < nfparams; u++)
1791 Argument *p = Argument::getNth(tf->parameters, u);
1792 Expression *e = p->type->defaultInit();
1793 args.data[u] = e;
1796 MATCH m = (MATCH) tg->callMatch(NULL, &args);
1797 if (m)
1799 /* A variadic template is less specialized than a
1800 * non-variadic one.
1802 if (tf->varargs && !tg->varargs)
1803 goto L1; // less specialized
1805 #if LOG_LEASTAS
1806 printf(" matches %d, so is least as specialized\n", m);
1807 #endif
1808 return m;
1811 #if LOG_LEASTAS
1812 printf(" doesn't match, so is not as specialized\n");
1813 #endif
1814 return MATCHnomatch;
1817 /********************************
1818 * Labels are in a separate scope, one per function.
1821 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
1822 { Dsymbol *s;
1824 if (!labtab)
1825 labtab = new DsymbolTable(); // guess we need one
1827 s = labtab->lookup(ident);
1828 if (!s)
1830 s = new LabelDsymbol(ident);
1831 labtab->insert(s);
1833 return (LabelDsymbol *)s;
1836 /****************************************
1837 * If non-static member function that has a 'this' pointer,
1838 * return the aggregate it is a member of.
1839 * Otherwise, return NULL.
1842 AggregateDeclaration *FuncDeclaration::isThis()
1843 { AggregateDeclaration *ad;
1845 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1846 ad = NULL;
1847 if ((storage_class & STCstatic) == 0)
1849 ad = isMember2();
1851 //printf("-FuncDeclaration::isThis() %p\n", ad);
1852 return ad;
1855 AggregateDeclaration *FuncDeclaration::isMember2()
1856 { AggregateDeclaration *ad;
1858 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1859 ad = NULL;
1860 for (Dsymbol *s = this; s; s = s->parent)
1862 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1863 ad = s->isMember();
1864 if (ad)
1865 { //printf("test4\n");
1866 break;
1868 if (!s->parent ||
1869 (!s->parent->isTemplateInstance()))
1870 { //printf("test5\n");
1871 break;
1874 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1875 return ad;
1878 /*****************************************
1879 * Determine lexical level difference from 'this' to nested function 'fd'.
1880 * Error if this cannot call fd.
1881 * Returns:
1882 * 0 same level
1883 * -1 increase nesting by 1 (fd is nested within 'this')
1884 * >0 decrease nesting by number
1887 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
1888 { int level;
1889 Dsymbol *s;
1890 Dsymbol *fdparent;
1892 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1893 fdparent = fd->toParent2();
1894 if (fdparent == this)
1895 return -1;
1896 s = this;
1897 level = 0;
1898 while (fd != s && fdparent != s->toParent2())
1900 //printf("\ts = '%s'\n", s->toChars());
1901 FuncDeclaration *thisfd = s->isFuncDeclaration();
1902 if (thisfd)
1903 { if (!thisfd->isNested() && !thisfd->vthis)
1904 goto Lerr;
1906 else
1908 ClassDeclaration *thiscd = s->isClassDeclaration();
1909 if (thiscd)
1910 { if (!thiscd->isNested())
1911 goto Lerr;
1913 else
1914 goto Lerr;
1917 s = s->toParent2();
1918 assert(s);
1919 level++;
1921 return level;
1923 Lerr:
1924 error(loc, "cannot access frame of function %s", fd->toChars());
1925 return 1;
1928 void FuncDeclaration::appendExp(Expression *e)
1929 { Statement *s;
1931 s = new ExpStatement(0, e);
1932 appendState(s);
1935 void FuncDeclaration::appendState(Statement *s)
1936 { CompoundStatement *cs;
1938 if (!fbody)
1939 { Statements *a;
1941 a = new Statements();
1942 fbody = new CompoundStatement(0, a);
1944 cs = fbody->isCompoundStatement();
1945 cs->statements->push(s);
1949 int FuncDeclaration::isMain()
1951 return ident == Id::main &&
1952 linkage != LINKc && !isMember() && !isNested();
1955 int FuncDeclaration::isWinMain()
1957 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
1958 #if 0
1959 int x = ident == Id::WinMain &&
1960 linkage != LINKc && !isMember();
1961 printf("%s\n", x ? "yes" : "no");
1962 return x;
1963 #else
1964 return ident == Id::WinMain &&
1965 linkage != LINKc && !isMember();
1966 #endif
1969 int FuncDeclaration::isDllMain()
1971 return ident == Id::DllMain &&
1972 linkage != LINKc && !isMember();
1975 int FuncDeclaration::isExport()
1977 return protection == PROTexport;
1980 int FuncDeclaration::isImportedSymbol()
1982 //printf("isImportedSymbol()\n");
1983 //printf("protection = %d\n", protection);
1984 return (protection == PROTexport) && !fbody;
1987 // Determine if function goes into virtual function pointer table
1989 int FuncDeclaration::isVirtual()
1991 #if 0
1992 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1993 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
1994 printf("result is %d\n",
1995 isMember() &&
1996 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1997 toParent()->isClassDeclaration());
1998 #endif
1999 return isMember() &&
2000 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2001 toParent()->isClassDeclaration();
2004 int FuncDeclaration::isFinal()
2006 #if 0
2007 printf("FuncDeclaration::isFinal(%s)\n", toChars());
2008 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2009 printf("result is %d\n",
2010 isMember() &&
2011 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2012 toParent()->isClassDeclaration());
2013 #endif
2014 ClassDeclaration *cd;
2015 return isMember() &&
2016 (Declaration::isFinal() ||
2017 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2020 int FuncDeclaration::isAbstract()
2022 return storage_class & STCabstract;
2025 int FuncDeclaration::isCodeseg()
2027 return TRUE; // functions are always in the code segment
2030 int FuncDeclaration::isOverloadable()
2032 return 1; // functions can be overloaded
2035 // Determine if function needs
2036 // a static frame pointer to its lexically enclosing function
2038 int FuncDeclaration::isNested()
2040 //if (!toParent())
2041 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2042 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2043 return ((storage_class & STCstatic) == 0) &&
2044 (toParent2()->isFuncDeclaration() != NULL);
2047 int FuncDeclaration::needThis()
2049 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2050 int i = isThis() != NULL;
2051 //printf("\t%d\n", i);
2052 if (!i && isFuncAliasDeclaration())
2053 i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
2054 return i;
2057 int FuncDeclaration::addPreInvariant()
2059 AggregateDeclaration *ad = isThis();
2060 return (ad &&
2061 //ad->isClassDeclaration() &&
2062 global.params.useInvariants &&
2063 (protection == PROTpublic || protection == PROTexport) &&
2064 !naked &&
2065 ident != Id::cpctor);
2068 int FuncDeclaration::addPostInvariant()
2070 AggregateDeclaration *ad = isThis();
2071 return (ad &&
2072 ad->inv &&
2073 //ad->isClassDeclaration() &&
2074 global.params.useInvariants &&
2075 (protection == PROTpublic || protection == PROTexport) &&
2076 !naked &&
2077 ident != Id::cpctor);
2080 /**********************************
2081 * Generate a FuncDeclaration for a runtime library function.
2084 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name,
2085 Type *t1, Type *t2, Type *t3)
2087 return genCfunc(treturn, Lexer::idPool(name), t1, t2, t3);
2090 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id,
2091 Type *t1, Type *t2, Type *t3)
2093 FuncDeclaration *fd;
2094 TypeFunction *tf;
2095 Dsymbol *s;
2096 static DsymbolTable *st = NULL;
2098 //printf("genCfunc(name = '%s')\n", id->toChars());
2099 //printf("treturn\n\t"); treturn->print();
2101 // See if already in table
2102 if (!st)
2103 st = new DsymbolTable();
2104 s = st->lookup(id);
2105 if (s)
2107 fd = s->isFuncDeclaration();
2108 assert(fd);
2109 assert(fd->type->nextOf()->equals(treturn));
2111 else
2113 Arguments * args = 0;
2114 if (t1) {
2115 args = new Arguments;
2116 args->push(new Argument(STCin,t1,0,0));
2117 if (t2)
2119 args->push(new Argument(STCin,t2,0,0));
2120 if (t3)
2121 args->push(new Argument(STCin,t3,0,0));
2125 tf = new TypeFunction(args, treturn, 0, LINKc);
2126 fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2127 fd->protection = PROTpublic;
2128 fd->linkage = LINKc;
2130 st->insert(fd);
2132 return fd;
2135 char *FuncDeclaration::kind()
2137 return "function";
2140 /*******************************
2141 * Look at all the variables in this function that are referenced
2142 * by nested functions, and determine if a closure needs to be
2143 * created for them.
2146 #if V2
2147 int FuncDeclaration::needsClosure()
2149 /* Need a closure for all the closureVars[] if any of the
2150 * closureVars[] are accessed by a
2151 * function that escapes the scope of this function.
2152 * We take the conservative approach and decide that any function that:
2153 * 1) is a virtual function
2154 * 2) has its address taken
2155 * 3) has a parent that escapes
2157 * Note that since a non-virtual function can be called by
2158 * a virtual one, if that non-virtual function accesses a closure
2159 * var, the closure still has to be taken. Hence, we check for isThis()
2160 * instead of isVirtual(). (thanks to David Friedman)
2163 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2164 for (int i = 0; i < closureVars.dim; i++)
2165 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
2166 assert(v->isVarDeclaration());
2167 //printf("\tv = %s\n", v->toChars());
2169 for (int j = 0; j < v->nestedrefs.dim; j++)
2170 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
2171 assert(f != this);
2173 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2174 if (f->isThis() || f->tookAddressOf)
2175 goto Lyes; // assume f escapes this function's scope
2177 // Look to see if any parents of f that are below this escape
2178 for (Dsymbol *s = f->parent; s != this; s = s->parent)
2180 f = s->isFuncDeclaration();
2181 if (f && (f->isThis() || f->tookAddressOf))
2182 goto Lyes;
2186 return 0;
2188 Lyes:
2189 //printf("\tneeds closure\n");
2190 return 1;
2192 #endif
2194 /****************************** FuncAliasDeclaration ************************/
2196 // Used as a way to import a set of functions from another scope into this one.
2198 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2199 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2200 (enum STC)funcalias->storage_class, funcalias->type)
2202 assert(funcalias != this);
2203 this->funcalias = funcalias;
2206 char *FuncAliasDeclaration::kind()
2208 return "function alias";
2212 /****************************** FuncLiteralDeclaration ************************/
2214 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2215 enum TOK tok, ForeachStatement *fes)
2216 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2218 char *id;
2220 if (fes)
2221 id = "__foreachbody";
2222 else if (tok == TOKdelegate)
2223 id = "__dgliteral";
2224 else
2225 id = "__funcliteral";
2226 this->ident = Identifier::generateId(id);
2227 this->tok = tok;
2228 this->fes = fes;
2229 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2232 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2234 FuncLiteralDeclaration *f;
2236 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2237 if (s)
2238 f = (FuncLiteralDeclaration *)s;
2239 else
2240 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2241 FuncDeclaration::syntaxCopy(f);
2242 return f;
2245 int FuncLiteralDeclaration::isNested()
2247 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2248 return (tok == TOKdelegate);
2251 char *FuncLiteralDeclaration::kind()
2253 // GCC requires the (char*) casts
2254 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
2257 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2259 static Identifier *idfunc;
2260 static Identifier *iddel;
2262 if (!idfunc)
2263 idfunc = new Identifier("function", 0);
2264 if (!iddel)
2265 iddel = new Identifier("delegate", 0);
2267 type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
2268 bodyToCBuffer(buf, hgs);
2272 /********************************* CtorDeclaration ****************************/
2274 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2275 : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
2277 this->arguments = arguments;
2278 this->varargs = varargs;
2279 //printf("CtorDeclaration() %s\n", toChars());
2282 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2284 CtorDeclaration *f;
2286 f = new CtorDeclaration(loc, endloc, NULL, varargs);
2288 f->outId = outId;
2289 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2290 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
2291 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
2292 assert(!fthrows); // deprecated
2294 f->arguments = Argument::arraySyntaxCopy(arguments);
2295 return f;
2299 void CtorDeclaration::semantic(Scope *sc)
2301 ClassDeclaration *cd;
2302 Type *tret;
2304 //printf("CtorDeclaration::semantic()\n");
2305 if (type)
2306 return;
2308 sc = sc->push();
2309 sc->stc &= ~STCstatic; // not a static constructor
2311 parent = sc->parent;
2312 Dsymbol *parent = toParent();
2313 cd = parent->isClassDeclaration();
2314 if (!cd)
2316 error("constructors are only for class definitions");
2317 tret = Type::tvoid;
2319 else
2321 tret = cd->type; //->referenceTo();
2323 for (int i = 0; i < cd->fields.dim; i++)
2325 VarDeclaration *vd = (VarDeclaration *) cd->fields.data[i];
2326 if (vd->isIn())
2328 if (!arguments)
2329 arguments = new Arguments();
2330 Argument *a = new Argument(vd->storage_class, vd->type, vd->ident, 0);
2331 // BUG: We don't really want these arguments in scope...
2332 arguments->push(a);
2334 Statement *assign = new ExpStatement(loc, new AssignExp(loc,
2335 new DotIdExp(loc, new ThisExp(loc), a->ident),
2336 new IdentifierExp(loc, a->ident)));
2337 if (fbody)
2338 fbody = new CompoundStatement(loc, assign, fbody);
2339 else
2340 fbody = assign;
2345 type = new TypeFunction(arguments, tret, varargs, LINKd);
2347 sc->flags |= SCOPEctor;
2348 type = type->semantic(loc, sc);
2349 sc->flags &= ~SCOPEctor;
2351 // Append:
2352 // return this;
2353 // to the function body
2354 if (fbody)
2355 { Expression *e;
2356 Statement *s;
2358 e = new ThisExp(0);
2359 s = new ReturnStatement(0, e);
2360 fbody = new CompoundStatement(0, fbody, s);
2363 FuncDeclaration::semantic(sc);
2365 sc->pop();
2367 // See if it's the default constructor
2368 if (cd && varargs == 0 && Argument::dim(arguments) == 0)
2369 cd->defaultCtor = this;
2372 char *CtorDeclaration::kind()
2374 return "constructor";
2377 char *CtorDeclaration::toChars()
2379 return "this";
2382 int CtorDeclaration::isVirtual()
2384 return FALSE;
2387 int CtorDeclaration::addPreInvariant()
2389 return FALSE;
2392 int CtorDeclaration::addPostInvariant()
2394 return (vthis && global.params.useInvariants);
2398 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2400 buf->writestring("this");
2401 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2402 bodyToCBuffer(buf, hgs);
2405 /********************************* PostBlitDeclaration ****************************/
2407 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
2408 : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
2412 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
2413 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2417 Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
2419 assert(!s);
2420 PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
2421 return FuncDeclaration::syntaxCopy(dd);
2425 void PostBlitDeclaration::semantic(Scope *sc)
2427 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2428 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2429 parent = sc->parent;
2430 Dsymbol *parent = toParent();
2431 StructDeclaration *ad = parent->isStructDeclaration();
2432 if (!ad)
2434 error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2436 else if (ident == Id::_postblit)
2437 ad->postblits.push(this);
2438 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2440 sc = sc->push();
2441 sc->stc &= ~STCstatic; // not static
2442 sc->linkage = LINKd;
2444 FuncDeclaration::semantic(sc);
2446 sc->pop();
2449 int PostBlitDeclaration::overloadInsert(Dsymbol *s)
2451 return FALSE; // cannot overload postblits
2454 int PostBlitDeclaration::addPreInvariant()
2456 return FALSE;
2459 int PostBlitDeclaration::addPostInvariant()
2461 return (vthis && global.params.useInvariants);
2464 int PostBlitDeclaration::isVirtual()
2466 return FALSE;
2469 void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2471 if (hgs->hdrgen)
2472 return;
2473 buf->writestring("=this()");
2474 bodyToCBuffer(buf, hgs);
2477 /********************************* DtorDeclaration ****************************/
2479 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
2480 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
2484 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
2485 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2489 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
2491 assert(!s);
2492 DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
2493 return FuncDeclaration::syntaxCopy(dd);
2497 void DtorDeclaration::semantic(Scope *sc)
2499 //printf("DtorDeclaration::semantic() %s\n", toChars());
2500 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2501 parent = sc->parent;
2502 Dsymbol *parent = toParent();
2503 AggregateDeclaration *ad = parent->isAggregateDeclaration();
2504 if (!ad)
2506 error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2508 else if (ident == Id::dtor)
2509 ad->dtors.push(this);
2510 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2512 sc = sc->push();
2513 sc->stc &= ~STCstatic; // not a static destructor
2514 sc->linkage = LINKd;
2516 FuncDeclaration::semantic(sc);
2518 sc->pop();
2521 int DtorDeclaration::overloadInsert(Dsymbol *s)
2523 return FALSE; // cannot overload destructors
2526 int DtorDeclaration::addPreInvariant()
2528 return (vthis && global.params.useInvariants);
2531 int DtorDeclaration::addPostInvariant()
2533 return FALSE;
2536 int DtorDeclaration::isVirtual()
2538 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2539 * but doing so will require recompiling everything.
2541 #if BREAKABI
2542 return FALSE;
2543 #else
2544 return FuncDeclaration::isVirtual();
2545 #endif
2548 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2550 if (hgs->hdrgen)
2551 return;
2552 buf->writestring("~this()");
2553 bodyToCBuffer(buf, hgs);
2556 /********************************* StaticCtorDeclaration ****************************/
2558 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
2559 : FuncDeclaration(loc, endloc,
2560 Identifier::generateId("_staticCtor"), STCstatic, NULL)
2564 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
2566 StaticCtorDeclaration *scd;
2568 assert(!s);
2569 scd = new StaticCtorDeclaration(loc, endloc);
2570 return FuncDeclaration::syntaxCopy(scd);
2574 void StaticCtorDeclaration::semantic(Scope *sc)
2576 //printf("StaticCtorDeclaration::semantic()\n");
2578 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2580 FuncDeclaration::semantic(sc);
2582 // We're going to need ModuleInfo
2583 Module *m = getModule();
2584 if (!m)
2585 m = sc->module;
2586 if (m)
2587 { m->needmoduleinfo = 1;
2588 #ifdef IN_GCC
2589 m->strictlyneedmoduleinfo = 1;
2590 #endif
2594 AggregateDeclaration *StaticCtorDeclaration::isThis()
2596 return NULL;
2599 int StaticCtorDeclaration::isStaticConstructor()
2601 return TRUE;
2604 int StaticCtorDeclaration::isVirtual()
2606 return FALSE;
2609 int StaticCtorDeclaration::addPreInvariant()
2611 return FALSE;
2614 int StaticCtorDeclaration::addPostInvariant()
2616 return FALSE;
2619 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2621 if (hgs->hdrgen)
2622 { buf->writestring("static this();\n");
2623 return;
2625 buf->writestring("static this()");
2626 bodyToCBuffer(buf, hgs);
2629 /********************************* StaticDtorDeclaration ****************************/
2631 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
2632 : FuncDeclaration(loc, endloc,
2633 Identifier::generateId("_staticDtor"), STCstatic, NULL)
2637 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
2639 StaticDtorDeclaration *sdd;
2641 assert(!s);
2642 sdd = new StaticDtorDeclaration(loc, endloc);
2643 return FuncDeclaration::syntaxCopy(sdd);
2647 void StaticDtorDeclaration::semantic(Scope *sc)
2649 ClassDeclaration *cd;
2650 Type *tret;
2652 cd = sc->scopesym->isClassDeclaration();
2653 if (!cd)
2656 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2658 FuncDeclaration::semantic(sc);
2660 // We're going to need ModuleInfo
2661 Module *m = getModule();
2662 if (!m)
2663 m = sc->module;
2664 if (m)
2665 { m->needmoduleinfo = 1;
2666 #ifdef IN_GCC
2667 m->strictlyneedmoduleinfo = 1;
2668 #endif
2672 AggregateDeclaration *StaticDtorDeclaration::isThis()
2674 return NULL;
2677 int StaticDtorDeclaration::isStaticDestructor()
2679 return TRUE;
2682 int StaticDtorDeclaration::isVirtual()
2684 return FALSE;
2687 int StaticDtorDeclaration::addPreInvariant()
2689 return FALSE;
2692 int StaticDtorDeclaration::addPostInvariant()
2694 return FALSE;
2697 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2699 if (hgs->hdrgen)
2700 return;
2701 buf->writestring("static ~this()");
2702 bodyToCBuffer(buf, hgs);
2705 /********************************* InvariantDeclaration ****************************/
2707 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
2708 : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
2712 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
2714 InvariantDeclaration *id;
2716 assert(!s);
2717 id = new InvariantDeclaration(loc, endloc);
2718 FuncDeclaration::syntaxCopy(id);
2719 return id;
2723 void InvariantDeclaration::semantic(Scope *sc)
2725 AggregateDeclaration *ad;
2726 Type *tret;
2728 parent = sc->parent;
2729 Dsymbol *parent = toParent();
2730 ad = parent->isAggregateDeclaration();
2731 if (!ad)
2733 error("invariants only are for struct/union/class definitions");
2734 return;
2736 else if (ad->inv && ad->inv != this)
2738 error("more than one invariant for %s", ad->toChars());
2740 ad->inv = this;
2741 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2743 sc = sc->push();
2744 sc->stc &= ~STCstatic; // not a static invariant
2745 sc->incontract++;
2746 sc->linkage = LINKd;
2748 FuncDeclaration::semantic(sc);
2750 sc->pop();
2753 int InvariantDeclaration::isVirtual()
2755 return FALSE;
2758 int InvariantDeclaration::addPreInvariant()
2760 return FALSE;
2763 int InvariantDeclaration::addPostInvariant()
2765 return FALSE;
2768 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2770 if (hgs->hdrgen)
2771 return;
2772 buf->writestring("invariant");
2773 bodyToCBuffer(buf, hgs);
2777 /********************************* UnitTestDeclaration ****************************/
2779 /*******************************
2780 * Generate unique unittest function Id so we can have multiple
2781 * instances per module.
2784 static Identifier *unitTestId()
2786 return Lexer::uniqueId("__unittest");
2789 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
2790 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
2794 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
2796 UnitTestDeclaration *utd;
2798 assert(!s);
2799 utd = new UnitTestDeclaration(loc, endloc);
2800 return FuncDeclaration::syntaxCopy(utd);
2804 void UnitTestDeclaration::semantic(Scope *sc)
2806 if (global.params.useUnitTests)
2808 Type *tret;
2810 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2811 FuncDeclaration::semantic(sc);
2814 // We're going to need ModuleInfo even if the unit tests are not
2815 // compiled in, because other modules may import this module and refer
2816 // to this ModuleInfo.
2817 Module *m = getModule();
2818 if (!m)
2819 m = sc->module;
2820 if (m)
2821 m->needmoduleinfo = 1;
2824 AggregateDeclaration *UnitTestDeclaration::isThis()
2826 return NULL;
2829 int UnitTestDeclaration::isVirtual()
2831 return FALSE;
2834 int UnitTestDeclaration::addPreInvariant()
2836 return FALSE;
2839 int UnitTestDeclaration::addPostInvariant()
2841 return FALSE;
2844 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2846 if (hgs->hdrgen)
2847 return;
2848 buf->writestring("unittest");
2849 bodyToCBuffer(buf, hgs);
2852 /********************************* NewDeclaration ****************************/
2854 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2855 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
2857 this->arguments = arguments;
2858 this->varargs = varargs;
2861 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
2863 NewDeclaration *f;
2865 f = new NewDeclaration(loc, endloc, NULL, varargs);
2867 FuncDeclaration::syntaxCopy(f);
2869 f->arguments = Argument::arraySyntaxCopy(arguments);
2871 return f;
2875 void NewDeclaration::semantic(Scope *sc)
2877 ClassDeclaration *cd;
2878 Type *tret;
2880 //printf("NewDeclaration::semantic()\n");
2882 parent = sc->parent;
2883 Dsymbol *parent = toParent();
2884 cd = parent->isClassDeclaration();
2885 if (!cd && !parent->isStructDeclaration())
2887 error("new allocators only are for class or struct definitions");
2889 tret = Type::tvoid->pointerTo();
2890 type = new TypeFunction(arguments, tret, varargs, LINKd);
2892 type = type->semantic(loc, sc);
2893 assert(type->ty == Tfunction);
2895 // Check that there is at least one argument of type uint
2896 TypeFunction *tf = (TypeFunction *)type;
2897 if (Argument::dim(tf->parameters) < 1)
2899 error("at least one argument of type uint expected");
2901 else
2903 Argument *a = Argument::getNth(tf->parameters, 0);
2904 if (!a->type->equals(Type::tuns32) &&
2905 (! global.params.isX86_64 || !a->type->equals(Type::tuns64)))
2906 error("first argument must be type uint, not %s", a->type->toChars());
2909 FuncDeclaration::semantic(sc);
2912 char *NewDeclaration::kind()
2914 return "allocator";
2917 int NewDeclaration::isVirtual()
2919 return FALSE;
2922 int NewDeclaration::addPreInvariant()
2924 return FALSE;
2927 int NewDeclaration::addPostInvariant()
2929 return FALSE;
2932 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2934 buf->writestring("new");
2935 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2936 bodyToCBuffer(buf, hgs);
2940 /********************************* DeleteDeclaration ****************************/
2942 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
2943 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
2945 this->arguments = arguments;
2948 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
2950 DeleteDeclaration *f;
2952 f = new DeleteDeclaration(loc, endloc, NULL);
2954 FuncDeclaration::syntaxCopy(f);
2956 f->arguments = Argument::arraySyntaxCopy(arguments);
2958 return f;
2962 void DeleteDeclaration::semantic(Scope *sc)
2964 ClassDeclaration *cd;
2966 //printf("DeleteDeclaration::semantic()\n");
2968 parent = sc->parent;
2969 Dsymbol *parent = toParent();
2970 cd = parent->isClassDeclaration();
2971 if (!cd && !parent->isStructDeclaration())
2973 error("new allocators only are for class or struct definitions");
2975 type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
2977 type = type->semantic(loc, sc);
2978 assert(type->ty == Tfunction);
2980 // Check that there is only one argument of type void*
2981 TypeFunction *tf = (TypeFunction *)type;
2982 if (Argument::dim(tf->parameters) != 1)
2984 error("one argument of type void* expected");
2986 else
2988 Argument *a = Argument::getNth(tf->parameters, 0);
2989 if (!a->type->equals(Type::tvoid->pointerTo()))
2990 error("one argument of type void* expected, not %s", a->type->toChars());
2993 FuncDeclaration::semantic(sc);
2996 char *DeleteDeclaration::kind()
2998 return "deallocator";
3001 int DeleteDeclaration::isDelete()
3003 return TRUE;
3006 int DeleteDeclaration::isVirtual()
3008 return FALSE;
3011 int DeleteDeclaration::addPreInvariant()
3013 return FALSE;
3016 int DeleteDeclaration::addPostInvariant()
3018 return FALSE;
3021 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3023 buf->writestring("delete");
3024 Argument::argsToCBuffer(buf, hgs, arguments, 0);
3025 bodyToCBuffer(buf, hgs);