Fix previous compiler crash without breaking functions with auto return types
[delight/core.git] / dmd2 / func.c
blob1b7064dbe8483f51b19a2e50b43c22334ba13553
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;
127 if (!type->deco && type->nextOf())
129 #if 1
130 /* Apply const and invariant storage class
131 * to the function type
133 type = type->semantic(loc, sc);
134 if (storage_class & STCinvariant)
135 { // Don't use toInvariant(), as that will do a merge()
136 type = type->makeInvariant();
137 type->deco = type->merge()->deco;
139 else if (storage_class & STCconst)
141 if (!type->isInvariant())
142 { // Don't use toConst(), as that will do a merge()
143 type = type->makeConst();
144 type->deco = type->merge()->deco;
147 #else
148 if (storage_class & (STCconst | STCinvariant))
150 /* Apply const and invariant storage class
151 * to the function's return type
153 Type *tn = type->nextOf();
154 if (storage_class & STCconst)
155 tn = tn->makeConst();
156 if (storage_class & STCinvariant)
157 tn = tn->makeInvariant();
158 ((TypeNext *)type)->next = tn;
161 type = type->semantic(loc, sc);
162 #endif
164 //type->print();
165 if (type->ty != Tfunction)
167 error("%s must be a function", toChars());
168 return;
170 f = (TypeFunction *)(type);
172 size_t nparams = Argument::dim(f->parameters);
174 linkage = sc->linkage;
175 // if (!parent)
177 //parent = sc->scopesym;
178 parent = sc->parent;
180 protection = sc->protection;
181 if (attributes)
182 attributes->append(sc->attributes);
183 else
184 attributes = sc->attributes;
185 Dsymbol *parent = toParent();
187 if (isAuto() || isScope())
188 error("functions cannot be scope or auto");
190 if (isAbstract() && !isVirtual())
191 error("non-virtual functions cannot be abstract");
193 if ((f->isConst() || f->isInvariant()) && !isThis())
194 error("without 'this' cannot be const/invariant");
196 if (isAbstract() && isFinal())
197 error("cannot be both final and abstract");
198 #if 0
199 if (isAbstract() && fbody)
200 error("abstract functions cannot have bodies");
201 #endif
203 #if 0
204 if (isStaticConstructor() || isStaticDestructor())
206 if (!isStatic() || type->nextOf()->ty != Tvoid)
207 error("static constructors / destructors must be static void");
208 if (f->arguments && f->arguments->dim)
209 error("static constructors / destructors must have empty parameter list");
210 // BUG: check for invalid storage classes
212 #endif
214 #ifdef IN_GCC
215 AggregateDeclaration *ad;
217 ad = parent->isAggregateDeclaration();
218 if (ad)
219 ad->methods.push(this);
220 #endif
221 sd = parent->isStructDeclaration();
222 if (sd)
224 // Verify no constructors, destructors, etc.
225 if (isCtorDeclaration()
226 //||isDtorDeclaration()
227 //|| isInvariantDeclaration()
228 //|| isUnitTestDeclaration()
231 error("special member functions not allowed for %ss", sd->kind());
234 #if 0
235 if (!sd->inv)
236 sd->inv = isInvariantDeclaration();
238 if (!sd->aggNew)
239 sd->aggNew = isNewDeclaration();
241 if (isDelete())
243 if (sd->aggDelete)
244 error("multiple delete's for struct %s", sd->toChars());
245 sd->aggDelete = (DeleteDeclaration *)(this);
247 #endif
250 id = parent->isInterfaceDeclaration();
251 if (id)
253 storage_class |= STCabstract;
255 if (isCtorDeclaration() ||
256 isPostBlitDeclaration() ||
257 isDtorDeclaration() ||
258 isInvariantDeclaration() ||
259 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
260 error("special function not allowed in interface %s", id->toChars());
261 if (fbody)
262 error("function body is not abstract in interface %s", id->toChars());
265 cd = parent->isClassDeclaration();
266 if (cd)
267 { int vi;
268 CtorDeclaration *ctor;
269 DtorDeclaration *dtor;
270 InvariantDeclaration *inv;
272 if (isCtorDeclaration())
274 // ctor = (CtorDeclaration *)this;
275 // if (!cd->ctor)
276 // cd->ctor = ctor;
277 return;
280 #if 0
281 dtor = isDtorDeclaration();
282 if (dtor)
284 if (cd->dtor)
285 error("multiple destructors for class %s", cd->toChars());
286 cd->dtor = dtor;
289 inv = isInvariantDeclaration();
290 if (inv)
292 cd->inv = inv;
295 if (isNewDeclaration())
297 if (!cd->aggNew)
298 cd->aggNew = (NewDeclaration *)(this);
301 if (isDelete())
303 if (cd->aggDelete)
304 error("multiple delete's for class %s", cd->toChars());
305 cd->aggDelete = (DeleteDeclaration *)(this);
307 #endif
309 if (storage_class & STCabstract)
310 cd->isabstract = 1;
312 // if static function, do not put in vtbl[]
313 if (!isVirtual())
315 //printf("\tnot virtual\n");
316 goto Ldone;
319 // Find index of existing function in vtbl[] to override
320 vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
321 switch (vi)
323 case -1:
324 /* Didn't find one, so
325 * This is an 'introducing' function which gets a new
326 * slot in the vtbl[].
329 // Verify this doesn't override previous final function
330 if (cd->baseClass)
331 { Dsymbol *s = cd->baseClass->search(loc, ident, 0);
332 if (s)
334 FuncDeclaration *f = s->isFuncDeclaration();
335 f = f->overloadExactMatch(type);
336 if (f && f->isFinal() && f->prot() != PROTprivate)
337 error("cannot override final function %s", f->toPrettyChars());
341 if (isFinal())
343 cd->vtblFinal.push(this);
345 else
347 // Append to end of vtbl[]
348 //printf("\tintroducing function\n");
349 introducing = 1;
350 vi = cd->vtbl.dim;
351 cd->vtbl.push(this);
352 vtblIndex = vi;
355 break;
357 case -2: // can't determine because of fwd refs
358 cd->sizeok = 2; // can't finish due to forward reference
359 return;
361 default:
362 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
363 // This function is covariant with fdv
364 if (fdv->isFinal())
365 error("cannot override final function %s", fdv->toPrettyChars());
367 if (!isOverride() && (global.params.warnings || sc->module->isDltFile))
368 error("overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
370 if (fdv->toParent() == parent)
372 // If both are mixins, then error.
373 // If either is not, the one that is not overrides
374 // the other.
375 if (fdv->parent->isClassDeclaration())
376 break;
377 if (!this->parent->isClassDeclaration()
378 #if !BREAKABI
379 && !isDtorDeclaration()
380 #endif
381 && !isPostBlitDeclaration()
383 error("multiple overrides of same function");
385 cd->vtbl.data[vi] = (void *)this;
386 vtblIndex = vi;
388 /* This works by whenever this function is called,
389 * it actually returns tintro, which gets dynamically
390 * cast to type. But we know that tintro is a base
391 * of type, so we could optimize it by not doing a
392 * dynamic cast, but just subtracting the isBaseOf()
393 * offset if the value is != null.
396 if (fdv->tintro)
397 tintro = fdv->tintro;
398 else if (!type->equals(fdv->type))
400 /* Only need to have a tintro if the vptr
401 * offsets differ
403 target_ptrdiff_t offset;
404 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
406 tintro = fdv->type;
409 break;
413 /* Go through all the interface bases.
414 * If this function is covariant with any members of those interface
415 * functions, set the tintro.
417 for (int i = 0; i < cd->interfaces_dim; i++)
419 BaseClass *b = cd->interfaces[i];
420 vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
421 switch (vi)
423 case -1:
424 break;
426 case -2:
427 cd->sizeok = 2; // can't finish due to forward reference
428 return;
430 default:
431 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
432 Type *ti = NULL;
434 if (fdv->tintro)
435 ti = fdv->tintro;
436 else if (!type->equals(fdv->type))
438 /* Only need to have a tintro if the vptr
439 * offsets differ
441 target_ptrdiff_t offset;
442 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
444 ti = fdv->type;
445 #if 0
446 if (offset)
447 ti = fdv->type;
448 else if (type->nextOf()->ty == Tclass)
449 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
450 if (cdn && cdn->sizeok != 1)
451 ti = fdv->type;
453 #endif
456 if (ti)
458 if (tintro && !tintro->equals(ti))
460 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
462 tintro = ti;
464 goto L2;
469 if (introducing && isOverride())
471 error("does not override any function");
474 L2: ;
476 else if (isOverride() && !parent->isTemplateInstance())
477 error("override only applies to class member functions");
479 /* Do not allow template instances to add virtual functions
480 * to a class.
482 if (isVirtual())
484 TemplateInstance *ti = parent->isTemplateInstance();
485 if (ti)
487 // Take care of nested templates
488 while (1)
490 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
491 if (!ti2)
492 break;
493 ti = ti2;
496 // If it's a member template
497 ClassDeclaration *cd = ti->tempdecl->isClassMember();
498 if (cd)
500 error("cannot use template to add virtual function to class '%s'", cd->toChars());
505 if (isMain())
507 // Check parameters to see if they are either () or (char[][] args)
508 switch (nparams)
510 case 0:
511 break;
513 case 1:
515 Argument *arg0 = Argument::getNth(f->parameters, 0);
516 if (arg0->type->ty != Tarray ||
517 arg0->type->nextOf()->ty != Tarray ||
518 arg0->type->nextOf()->nextOf()->ty != Tchar ||
519 arg0->storageClass & (STCout | STCref | STClazy))
520 goto Lmainerr;
521 break;
524 default:
525 goto Lmainerr;
528 if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
529 error("must return int or void, not %s", f->nextOf()->toChars());
530 if (f->varargs)
532 Lmainerr:
533 error("parameters must be main() or main(char[][] args)");
537 if (ident == Id::assign && (sd || cd))
538 { // Disallow identity assignment operator.
540 // opAssign(...)
541 if (nparams == 0)
542 { if (f->varargs == 1)
543 goto Lassignerr;
545 else
547 Argument *arg0 = Argument::getNth(f->parameters, 0);
548 Type *t0 = arg0->type->toBasetype();
549 Type *tb = sd ? sd->type : cd->type;
550 if (arg0->type->implicitConvTo(tb) ||
551 (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
554 if (nparams == 1)
555 goto Lassignerr;
556 Argument *arg1 = Argument::getNth(f->parameters, 1);
557 if (arg1->defaultArg)
558 goto Lassignerr;
563 Ldone:
564 /* Save scope for possible later use (if we need the
565 * function internals)
567 scope = new Scope(*sc);
568 scope->setNoFree();
569 return;
571 Lassignerr:
572 if (sd)
574 sd->hasIdentityAssign = 1; // don't need to generate it
575 goto Ldone;
577 error("identity assignment operator overload is illegal");
580 void FuncDeclaration::semantic2(Scope *sc)
584 // Do the semantic analysis on the internals of the function.
586 void FuncDeclaration::semantic3(Scope *sc)
587 { TypeFunction *f;
588 AggregateDeclaration *ad;
589 VarDeclaration *argptr = NULL;
590 VarDeclaration *_arguments = NULL;
592 if (!parent)
594 if (global.errors)
595 return;
596 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
597 assert(0);
599 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
600 //fflush(stdout);
601 //{ static int x; if (++x == 2) *(char*)0=0; }
602 //printf("\tlinkage = %d\n", sc->linkage);
604 //printf(" sc->incontract = %d\n", sc->incontract);
605 if (semanticRun)
606 return;
607 semanticRun = 1;
609 if (!type || type->ty != Tfunction)
610 return;
611 f = (TypeFunction *)(type);
613 // Check the 'throws' clause
614 if (fthrows)
615 { int i;
617 for (i = 0; i < fthrows->dim; i++)
619 Type *t = (Type *)fthrows->data[i];
621 t = t->semantic(loc, sc);
622 if (!t->isClassHandle())
623 error("can only throw classes, not %s", t->toChars());
627 if (fbody || frequire)
629 /* Symbol table into which we place parameters and nested functions,
630 * solely to diagnose name collisions.
632 localsymtab = new DsymbolTable();
634 // Establish function scope
635 ScopeDsymbol *ss = new ScopeDsymbol();
636 ss->parent = sc->scopesym;
637 Scope *sc2 = sc->push(ss);
638 sc2->func = this;
639 sc2->parent = this;
640 sc2->callSuper = 0;
641 sc2->sbreak = NULL;
642 sc2->scontinue = NULL;
643 sc2->sw = NULL;
644 sc2->fes = fes;
645 sc2->linkage = LINKd;
646 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCconst | STCfinal | STCinvariant | STCtls);
647 sc2->attributes = NULL;
648 sc2->protection = PROTpublic;
649 sc2->explicitProtection = 0;
650 sc2->structalign = 8;
651 sc2->incontract = 0;
652 sc2->tf = NULL;
653 sc2->noctor = 0;
655 // Declare 'this'
656 ad = isThis();
657 if (ad)
658 { VarDeclaration *v;
660 if (isFuncLiteralDeclaration() && isNested())
662 error("literals cannot be class members");
663 return;
665 else
667 assert(!isNested()); // can't be both member and nested
668 assert(ad->handle);
669 Type *thandle = ad->handle;
670 if (storage_class & STCconst || type->isConst())
672 if (thandle->ty == Tclass)
673 thandle = thandle->constOf();
674 else
675 { assert(thandle->ty == Tpointer);
676 thandle = thandle->nextOf()->constOf()->pointerTo();
679 else if (storage_class & STCinvariant || type->isInvariant())
681 if (thandle->ty == Tclass)
682 thandle = thandle->invariantOf();
683 else
684 { assert(thandle->ty == Tpointer);
685 thandle = thandle->nextOf()->invariantOf()->pointerTo();
688 v = new ThisDeclaration(thandle);
689 v->storage_class |= STCparameter;
690 v->semantic(sc2);
691 if (!sc2->insert(v))
692 assert(0);
693 v->parent = this;
694 vthis = v;
697 else if (isNested())
699 /* The 'this' for a nested function is the link to the
700 * enclosing function's stack frame.
701 * Note that nested functions and member functions are disjoint.
703 VarDeclaration *v = new ThisDeclaration(Type::tvoid->pointerTo());
704 v->storage_class |= STCparameter;
705 v->semantic(sc2);
706 if (!sc2->insert(v))
707 assert(0);
708 v->parent = this;
709 vthis = v;
712 // Declare hidden variable _arguments[] and _argptr
713 if (f->varargs == 1)
714 { Type *t;
716 if (f->linkage == LINKd)
717 { // Declare _arguments[]
718 #if BREAKABI
719 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
720 v_arguments->storage_class = STCparameter;
721 v_arguments->semantic(sc2);
722 sc2->insert(v_arguments);
723 v_arguments->parent = this;
725 //t = Type::typeinfo->type->constOf()->arrayOf();
726 t = Type::typeinfo->type->arrayOf();
727 _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
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->semantic(sc2);
749 sc2->insert(argptr);
750 argptr->parent = this;
754 // Propagate storage class from tuple parameters to their element-parameters.
755 if (f->parameters)
757 for (size_t i = 0; i < f->parameters->dim; i++)
758 { Argument *arg = (Argument *)f->parameters->data[i];
760 if (arg->type->ty == Ttuple)
761 { TypeTuple *t = (TypeTuple *)arg->type;
762 size_t dim = Argument::dim(t->arguments);
763 for (size_t j = 0; j < dim; j++)
764 { Argument *narg = Argument::getNth(t->arguments, j);
765 narg->storageClass = arg->storageClass;
771 /* Declare all the function parameters as variables
772 * and install them in parameters[]
774 size_t nparams = Argument::dim(f->parameters);
775 if (nparams)
776 { /* parameters[] has all the tuples removed, as the back end
777 * doesn't know about tuples
779 parameters = new Dsymbols();
780 parameters->reserve(nparams);
781 for (size_t i = 0; i < nparams; i++)
783 Argument *arg = Argument::getNth(f->parameters, i);
784 Identifier *id = arg->ident;
785 if (!id)
787 /* Generate identifier for un-named parameter,
788 * because we need it later on.
790 OutBuffer buf;
791 buf.printf("_param_%"PRIuSIZE, i);
792 char *name = (char *)buf.extractData();
793 id = new Identifier(name, TOKidentifier);
794 arg->ident = id;
796 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
797 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
798 v->storage_class |= STCparameter;
799 if (f->varargs == 2 && i + 1 == nparams)
800 v->storage_class |= STCvariadic;
801 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STCconst | STCinvariant | STCnodtor);
802 v->semantic(sc2);
803 if (!sc2->insert(v))
804 error("parameter %s.%s is already defined", toChars(), v->toChars());
805 else
806 parameters->push(v);
807 localsymtab->insert(v);
808 v->parent = this;
812 // Declare the tuple symbols and put them in the symbol table,
813 // but not in parameters[].
814 if (f->parameters)
816 for (size_t i = 0; i < f->parameters->dim; i++)
817 { Argument *arg = (Argument *)f->parameters->data[i];
819 if (!arg->ident)
820 continue; // never used, so ignore
821 if (arg->type->ty == Ttuple)
822 { TypeTuple *t = (TypeTuple *)arg->type;
823 size_t dim = Argument::dim(t->arguments);
824 Objects *exps = new Objects();
825 exps->setDim(dim);
826 for (size_t j = 0; j < dim; j++)
827 { Argument *narg = Argument::getNth(t->arguments, j);
828 assert(narg->ident);
829 VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
830 assert(v);
831 Expression *e = new VarExp(v->loc, v);
832 exps->data[j] = (void *)e;
834 assert(arg->ident);
835 TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
836 //printf("declaring tuple %s\n", v->toChars());
837 v->isexp = 1;
838 if (!sc2->insert(v))
839 error("parameter %s.%s is already defined", toChars(), v->toChars());
840 localsymtab->insert(v);
841 v->parent = this;
846 /* Do the semantic analysis on the [in] preconditions and
847 * [out] postconditions.
849 sc2->incontract++;
851 if (frequire)
852 { /* frequire is composed of the [in] contracts
854 // BUG: need to error if accessing out parameters
855 // BUG: need to treat parameters as const
856 // BUG: need to disallow returns and throws
857 // BUG: verify that all in and ref parameters are read
858 frequire = frequire->semantic(sc2);
859 labtab = NULL; // so body can't refer to labels
862 if (fensure || addPostInvariant())
863 { /* fensure is composed of the [out] contracts
865 ScopeDsymbol *sym = new ScopeDsymbol();
866 sym->parent = sc2->scopesym;
867 sc2 = sc2->push(sym);
869 assert(type->nextOf());
870 if (type->nextOf()->ty == Tvoid)
872 if (outId)
873 error("void functions have no result");
875 else
877 if (!outId)
878 outId = Id::result; // provide a default
881 if (outId)
882 { // Declare result variable
883 VarDeclaration *v;
884 Loc loc = this->loc;
886 if (fensure)
887 loc = fensure->loc;
889 v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
890 v->noauto = 1;
891 sc2->incontract--;
892 v->semantic(sc2);
893 sc2->incontract++;
894 if (!sc2->insert(v))
895 error("out result %s is already defined", v->toChars());
896 v->parent = this;
897 vresult = v;
899 // vresult gets initialized with the function return value
900 // in ReturnStatement::semantic()
903 // BUG: need to treat parameters as const
904 // BUG: need to disallow returns and throws
905 if (fensure)
906 { fensure = fensure->semantic(sc2);
907 labtab = NULL; // so body can't refer to labels
910 if (!global.params.useOut)
911 { fensure = NULL; // discard
912 vresult = NULL;
915 // Postcondition invariant
916 if (addPostInvariant())
918 Expression *e = NULL;
919 if (isCtorDeclaration())
921 // Call invariant directly only if it exists
922 InvariantDeclaration *inv = ad->inv;
923 ClassDeclaration *cd = ad->isClassDeclaration();
925 while (!inv && cd)
927 cd = cd->baseClass;
928 if (!cd)
929 break;
930 inv = cd->inv;
932 if (inv)
934 e = new DsymbolExp(0, inv);
935 e = new CallExp(0, e);
936 e = e->semantic(sc2);
939 else
940 { // Call invariant virtually
941 ThisExp *v = new ThisExp(0);
942 v->type = vthis->type;
943 e = new AssertExp(0, v);
945 if (e)
947 ExpStatement *s = new ExpStatement(0, e);
948 if (fensure)
949 fensure = new CompoundStatement(0, s, fensure);
950 else
951 fensure = s;
955 if (fensure)
956 { returnLabel = new LabelDsymbol(Id::returnLabel);
957 LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
958 ls->isReturnLabel = 1;
959 returnLabel->statement = ls;
961 sc2 = sc2->pop();
964 sc2->incontract--;
966 if (fbody)
967 { ClassDeclaration *cd = isClassMember();
969 /* If this is a class constructor
971 if (isCtorDeclaration() && cd)
973 for (int i = 0; i < cd->fields.dim; i++)
974 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
976 v->ctorinit = 0;
980 if (inferRetType || f->retStyle() != RETstack)
981 nrvo_can = 0;
983 fbody = fbody->semantic(sc2);
985 if (inferRetType)
986 { // If no return type inferred yet, then infer a void
987 if (!type->nextOf())
989 ((TypeFunction *)type)->next = Type::tvoid;
990 type = type->semantic(loc, sc);
992 f = (TypeFunction *)type;
995 if (isStaticCtorDeclaration())
996 { /* It's a static constructor. Ensure that all
997 * ctor consts were initialized.
1000 Dsymbol *p = toParent();
1001 ScopeDsymbol *ad = p->isScopeDsymbol();
1002 if (!ad)
1004 error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
1006 else
1008 for (int i = 0; i < ad->members->dim; i++)
1009 { Dsymbol *s = (Dsymbol *)ad->members->data[i];
1011 s->checkCtorConstInit();
1016 if (isCtorDeclaration() && cd)
1018 //printf("callSuper = x%x\n", sc2->callSuper);
1020 // Verify that all the ctorinit fields got initialized
1021 // Also check that non-null members got set
1022 if (!(sc2->callSuper & CSXthis_ctor))
1024 for (int i = 0; i < cd->fields.dim; i++)
1025 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
1027 if (v->ctorinit == 0)
1029 if (v->isCtorinit())
1030 error("missing initializer for final field %s", v->toChars());
1031 else if (v->requirePointerInit &&
1032 (v->type->ty == Tclass || v->type->ty == Tpointer))
1033 error("missing initializer for non-null field %s", v->toChars());
1038 if (!(sc2->callSuper & CSXany_ctor) &&
1039 cd->baseClass && cd->baseClass->ctor)
1041 sc2->callSuper = 0;
1043 // Insert implicit super() at start of fbody
1044 Expression *e1 = new SuperExp(0);
1045 Expression *e = new CallExp(0, e1);
1047 unsigned errors = global.errors;
1048 global.gag++;
1049 e = e->semantic(sc2);
1050 global.gag--;
1051 if (errors != global.errors)
1052 error("no match for implicit super() call in constructor");
1054 Statement *s = new ExpStatement(0, e);
1055 fbody = new CompoundStatement(0, s, fbody);
1058 else if (fes)
1059 { // For foreach(){} body, append a return 0;
1060 Expression *e = new IntegerExp(0);
1061 Statement *s = new ReturnStatement(0, e);
1062 fbody = new CompoundStatement(0, fbody, s);
1063 assert(!returnLabel);
1065 else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1066 error("expected to return a value of type %s", type->nextOf()->toChars());
1067 else if (!inlineAsm)
1069 int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
1070 //int offend = fbody ? fbody->fallOffEnd() : TRUE;
1072 if (type->nextOf()->ty == Tvoid)
1074 if (offend && isMain())
1075 { // Add a return 0; statement
1076 Statement *s = new ReturnStatement(0, new IntegerExp(0));
1077 fbody = new CompoundStatement(0, fbody, s);
1080 else
1082 if (offend)
1083 { Expression *e;
1085 if (global.params.warnings)
1086 { fprintf(stdmsg, "warning - ");
1087 error("no return at end of function");
1090 if (global.params.useAssert &&
1091 !global.params.useInline)
1092 { /* Add an assert(0, msg); where the missing return
1093 * should be.
1095 e = new AssertExp(
1096 endloc,
1097 new IntegerExp(0),
1098 new StringExp(loc, "missing return expression")
1101 else
1102 e = new HaltExp(endloc);
1103 e = new CommaExp(0, e, type->nextOf()->defaultInit());
1104 e = e->semantic(sc2);
1105 Statement *s = new ExpStatement(0, e);
1106 fbody = new CompoundStatement(0, fbody, s);
1113 Statements *a = new Statements();
1115 // Merge in initialization of 'out' parameters
1116 if (parameters)
1117 { for (size_t i = 0; i < parameters->dim; i++)
1119 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1120 if (v->storage_class & STCout)
1122 assert(v->init);
1123 ExpInitializer *ie = v->init->isExpInitializer();
1124 assert(ie);
1125 a->push(new ExpStatement(0, ie->exp));
1130 if (argptr)
1131 { // Initialize _argptr to point past non-variadic arg
1132 #if IN_GCC
1133 // Handled in FuncDeclaration::toObjFile
1134 v_argptr = argptr;
1135 v_argptr->init = new VoidInitializer(loc);
1136 #else
1137 Expression *e1;
1138 Expression *e;
1139 Type *t = argptr->type;
1140 VarDeclaration *p;
1141 unsigned offset;
1143 e1 = new VarExp(0, argptr);
1144 if (parameters && parameters->dim)
1145 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1146 else
1147 p = v_arguments; // last parameter is _arguments[]
1148 offset = p->type->size();
1149 offset = (offset + 3) & ~3; // assume stack aligns on 4
1150 e = new SymOffExp(0, p, offset);
1151 e = new AssignExp(0, e1, e);
1152 e->type = t;
1153 a->push(new ExpStatement(0, e));
1154 #endif
1157 if (_arguments)
1159 #if IN_GCC
1160 v_arguments_var = _arguments;
1161 v_arguments_var->init = new VoidInitializer(loc);
1162 #endif
1163 /* Advance to elements[] member of TypeInfo_Tuple with:
1164 * _arguments = v_arguments.elements;
1166 Expression *e = new VarExp(0, v_arguments);
1167 e = new DotIdExp(0, e, Id::elements);
1168 Expression *e1 = new VarExp(0, _arguments);
1169 e = new AssignExp(0, e1, e);
1170 e->op = TOKconstruct;
1171 e = e->semantic(sc);
1172 a->push(new ExpStatement(0, e));
1175 // Merge contracts together with body into one compound statement
1177 #ifdef _DH
1178 if (frequire && global.params.useIn)
1179 { frequire->incontract = 1;
1180 a->push(frequire);
1182 #else
1183 if (frequire && global.params.useIn)
1184 a->push(frequire);
1185 #endif
1187 // Precondition invariant
1188 if (addPreInvariant())
1190 Expression *e = NULL;
1191 if (isDtorDeclaration())
1193 // Call invariant directly only if it exists
1194 InvariantDeclaration *inv = ad->inv;
1195 ClassDeclaration *cd = ad->isClassDeclaration();
1197 while (!inv && cd)
1199 cd = cd->baseClass;
1200 if (!cd)
1201 break;
1202 inv = cd->inv;
1204 if (inv)
1206 e = new DsymbolExp(0, inv);
1207 e = new CallExp(0, e);
1208 e = e->semantic(sc2);
1211 else
1212 { // Call invariant virtually
1213 ThisExp *v = new ThisExp(0);
1214 v->type = vthis->type;
1215 Expression *se = new StringExp(0, "null this");
1216 se = se->semantic(sc);
1217 se->type = Type::tchar->arrayOf();
1218 e = new AssertExp(loc, v, se);
1220 if (e)
1222 ExpStatement *s = new ExpStatement(0, e);
1223 a->push(s);
1227 if (fbody)
1228 a->push(fbody);
1230 if (fensure)
1232 a->push(returnLabel->statement);
1234 if (type->nextOf()->ty != Tvoid)
1236 // Create: return vresult;
1237 assert(vresult);
1238 Expression *e = new VarExp(0, vresult);
1239 if (tintro)
1240 { e = e->implicitCastTo(sc, tintro->nextOf());
1241 e = e->semantic(sc);
1243 ReturnStatement *s = new ReturnStatement(0, e);
1244 a->push(s);
1248 fbody = new CompoundStatement(0, a);
1250 /* Append destructor calls for parameters as finally blocks.
1252 if (parameters)
1253 { for (size_t i = 0; i < parameters->dim; i++)
1255 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1257 if (v->storage_class & (STCref | STCout))
1258 continue;
1260 /* Don't do this for static arrays, since static
1261 * arrays are called by reference. Remove this
1262 * when we change them to call by value.
1264 if (v->type->toBasetype()->ty == Tsarray)
1265 continue;
1267 Expression *e = v->callAutoDtor(sc);
1268 if (e)
1269 { Statement *s = new ExpStatement(0, e);
1270 s = s->semantic(sc);
1271 if (fbody->blockExit() == BEfallthru)
1272 fbody = new CompoundStatement(0, fbody, s);
1273 else
1274 fbody = new TryFinallyStatement(0, fbody, s);
1280 sc2->callSuper = 0;
1281 sc2->pop();
1283 semanticRun = 2;
1286 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1288 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1290 type->toCBuffer(buf, ident, hgs);
1291 bodyToCBuffer(buf, hgs);
1295 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1297 if (fbody &&
1298 (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1300 { buf->writenl();
1302 // in{}
1303 if (frequire)
1304 { buf->writestring("in");
1305 buf->writenl();
1306 frequire->toCBuffer(buf, hgs);
1309 // out{}
1310 if (fensure)
1311 { buf->writestring("out");
1312 if (outId)
1313 { buf->writebyte('(');
1314 buf->writestring(outId->toChars());
1315 buf->writebyte(')');
1317 buf->writenl();
1318 fensure->toCBuffer(buf, hgs);
1321 if (frequire || fensure)
1322 { buf->writestring("body");
1323 buf->writenl();
1326 buf->writebyte('{');
1327 buf->writenl();
1328 fbody->toCBuffer(buf, hgs);
1329 buf->writebyte('}');
1330 buf->writenl();
1332 else
1333 { buf->writeByte(';');
1334 buf->writenl();
1338 /****************************************************
1339 * Determine if 'this' overrides fd.
1340 * Return !=0 if it does.
1343 int FuncDeclaration::overrides(FuncDeclaration *fd)
1344 { int result = 0;
1346 if (fd->ident == ident)
1348 int cov = type->covariant(fd->type);
1349 if (cov)
1350 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1351 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1353 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1354 result = 1;
1357 return result;
1360 /*************************************************
1361 * Find index of function in vtbl[0..dim] that
1362 * this function overrides.
1363 * Returns:
1364 * -1 didn't find one
1365 * -2 can't determine because of forward references
1368 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
1370 for (int vi = 0; vi < dim; vi++)
1372 FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
1373 if (fdv && fdv->ident == ident)
1375 int cov = type->covariant(fdv->type);
1376 //printf("\tbaseclass cov = %d\n", cov);
1377 switch (cov)
1379 case 0: // types are distinct
1380 break;
1382 case 1:
1383 return vi;
1385 case 2:
1386 //type->print();
1387 //fdv->type->print();
1388 //printf("%s %s\n", type->deco, fdv->type->deco);
1389 error("of type %s overrides but is not covariant with %s of type %s",
1390 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
1391 break;
1393 case 3:
1394 return -2; // forward references
1396 default:
1397 assert(0);
1401 return -1;
1404 /****************************************************
1405 * Overload this FuncDeclaration with the new one f.
1406 * Return !=0 if successful; i.e. no conflict.
1409 int FuncDeclaration::overloadInsert(Dsymbol *s)
1411 FuncDeclaration *f;
1412 AliasDeclaration *a;
1414 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1415 a = s->isAliasDeclaration();
1416 if (a)
1418 if (overnext)
1419 return overnext->overloadInsert(a);
1420 if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1422 //printf("\ta = '%s'\n", a->type->toChars());
1423 return FALSE;
1425 overnext = a;
1426 //printf("\ttrue: no conflict\n");
1427 return TRUE;
1429 f = s->isFuncDeclaration();
1430 if (!f)
1431 return FALSE;
1433 #if 0
1434 /* Disable this check because:
1435 * const void foo();
1436 * semantic() isn't run yet on foo(), so the const hasn't been
1437 * applied yet.
1439 if (type)
1440 { printf("type = %s\n", type->toChars());
1441 printf("f->type = %s\n", f->type->toChars());
1443 if (type && f->type && // can be NULL for overloaded constructors
1444 f->type->covariant(type) &&
1445 f->type->mod == type->mod &&
1446 !isFuncAliasDeclaration())
1448 //printf("\tfalse: conflict %s\n", kind());
1449 return FALSE;
1451 #endif
1453 if (overnext)
1454 return overnext->overloadInsert(f);
1455 overnext = f;
1456 //printf("\ttrue: no conflict\n");
1457 return TRUE;
1460 /***************************************************
1461 * Visit each overloaded function in turn, and call
1462 * (*fp)(param, f) on it.
1463 * Exit when no more, or (*fp)(param, f) returns 1.
1464 * Returns:
1465 * 0 continue
1466 * 1 done
1469 int overloadApply(FuncDeclaration *fstart,
1470 int (*fp)(void *, FuncDeclaration *),
1471 void *param)
1473 FuncDeclaration *f;
1474 Declaration *d;
1475 Declaration *next;
1477 for (d = fstart; d; d = next)
1478 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1480 if (fa)
1482 if (overloadApply(fa->funcalias, fp, param))
1483 return 1;
1484 next = fa->overnext;
1486 else
1488 AliasDeclaration *a = d->isAliasDeclaration();
1490 if (a)
1492 Dsymbol *s = a->toAlias();
1493 next = s->isDeclaration();
1494 if (next == a)
1495 break;
1496 if (next == fstart)
1497 break;
1499 else
1501 f = d->isFuncDeclaration();
1502 if (!f)
1503 { d->error("is aliased to a function");
1504 break; // BUG: should print error message?
1506 if ((*fp)(param, f))
1507 return 1;
1509 next = f->overnext;
1513 return 0;
1516 /********************************************
1517 * If there are no overloads of function f, return that function,
1518 * otherwise return NULL.
1521 static int fpunique(void *param, FuncDeclaration *f)
1522 { FuncDeclaration **pf = (FuncDeclaration **)param;
1524 if (*pf)
1525 { *pf = NULL;
1526 return 1; // ambiguous, done
1528 else
1529 { *pf = f;
1530 return 0;
1534 FuncDeclaration *FuncDeclaration::isUnique()
1535 { FuncDeclaration *result = NULL;
1537 overloadApply(this, &fpunique, &result);
1538 return result;
1541 /********************************************
1542 * Find function in overload list that exactly matches t.
1545 struct Param1
1547 Type *t; // type to match
1548 FuncDeclaration *f; // return value
1551 int fp1(void *param, FuncDeclaration *f)
1552 { Param1 *p = (Param1 *)param;
1553 Type *t = p->t;
1555 if (t->equals(f->type))
1556 { p->f = f;
1557 return 1;
1560 #if V2
1561 /* Allow covariant matches, if it's just a const conversion
1562 * of the return type
1564 if (t->ty == Tfunction)
1565 { TypeFunction *tf = (TypeFunction *)f->type;
1566 if (tf->covariant(t) == 1 &&
1567 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
1569 p->f = f;
1570 return 1;
1573 #endif
1574 return 0;
1577 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1579 Param1 p;
1580 p.t = t;
1581 p.f = NULL;
1582 overloadApply(this, &fp1, &p);
1583 return p.f;
1587 /********************************************
1588 * Decide which function matches the arguments best.
1591 struct Param2
1593 Match *m;
1594 Expression *ethis;
1595 Expressions *arguments;
1598 int fp2(void *param, FuncDeclaration *f)
1599 { Param2 *p = (Param2 *)param;
1600 Match *m = p->m;
1601 Expressions *arguments = p->arguments;
1602 MATCH match;
1604 if (f != m->lastf) // skip duplicates
1606 m->anyf = f;
1607 TypeFunction *tf = (TypeFunction *)f->type;
1608 match = (MATCH) tf->callMatch(f->needThis() ? p->ethis : NULL, arguments);
1609 //printf("match = %d\n", match);
1610 if (match != MATCHnomatch)
1612 if (match > m->last)
1613 goto LfIsBetter;
1615 if (match < m->last)
1616 goto LlastIsBetter;
1618 /* See if one of the matches overrides the other.
1620 if (m->lastf->overrides(f))
1621 goto LlastIsBetter;
1622 else if (f->overrides(m->lastf))
1623 goto LfIsBetter;
1625 /* Try to disambiguate using template-style partial ordering rules.
1626 * In essence, if f() and g() are ambiguous, if f() can call g(),
1627 * but g() cannot call f(), then pick f().
1628 * This is because f() is "more specialized."
1631 MATCH c1 = f->leastAsSpecialized(m->lastf);
1632 MATCH c2 = m->lastf->leastAsSpecialized(f);
1633 if (c1 > c2)
1634 goto LfIsBetter;
1635 if (c1 < c2)
1636 goto LlastIsBetter;
1639 Lambiguous:
1640 m->nextf = f;
1641 m->count++;
1642 return 0;
1644 LfIsBetter:
1645 m->last = match;
1646 m->lastf = f;
1647 m->count = 1;
1648 return 0;
1650 LlastIsBetter:
1651 return 0;
1654 return 0;
1657 void overloadResolveX(Match *m, FuncDeclaration *fstart,
1658 Expression *ethis, Expressions *arguments)
1660 Param2 p;
1661 p.m = m;
1662 p.ethis = ethis;
1663 p.arguments = arguments;
1664 overloadApply(fstart, &fp2, &p);
1668 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags)
1670 TypeFunction *tf;
1671 Match m;
1673 #if 0
1674 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1675 if (arguments)
1676 { int i;
1678 for (i = 0; i < arguments->dim; i++)
1679 { Expression *arg;
1681 arg = (Expression *)arguments->data[i];
1682 assert(arg->type);
1683 printf("\t%s: ", arg->toChars());
1684 arg->type->print();
1687 #endif
1689 memset(&m, 0, sizeof(m));
1690 m.last = MATCHnomatch;
1691 overloadResolveX(&m, this, ethis, arguments);
1693 if (m.count == 1) // exactly one match
1695 return m.lastf;
1697 else
1699 OutBuffer buf;
1701 if (arguments)
1703 HdrGenState hgs;
1705 argExpTypesToCBuffer(&buf, arguments, &hgs);
1708 if (m.last == MATCHnomatch)
1710 if (flags & 1) // if do not print error messages
1711 return NULL; // no match
1713 tf = (TypeFunction *)type;
1715 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1716 error(loc, "%s does not match parameter types (%s)",
1717 Argument::argsTypesToChars(tf->parameters, tf->varargs),
1718 buf.toChars());
1719 return m.anyf; // as long as it's not a FuncAliasDeclaration
1721 else
1723 #if 1
1724 TypeFunction *t1 = (TypeFunction *)m.lastf->type;
1725 TypeFunction *t2 = (TypeFunction *)m.nextf->type;
1727 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1728 buf.toChars(),
1729 m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
1730 m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
1731 #else
1732 error(loc, "overloads %s and %s both match argument list for %s",
1733 m.lastf->type->toChars(),
1734 m.nextf->type->toChars(),
1735 m.lastf->toChars());
1736 #endif
1737 return m.lastf;
1742 /*************************************
1743 * Determine partial specialization order of 'this' vs g.
1744 * This is very similar to TemplateDeclaration::leastAsSpecialized().
1745 * Returns:
1746 * match 'this' is at least as specialized as g
1747 * 0 g is more specialized than 'this'
1750 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
1752 #define LOG_LEASTAS 0
1754 #if LOG_LEASTAS
1755 printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
1756 #endif
1758 /* This works by calling g() with f()'s parameters, and
1759 * if that is possible, then f() is at least as specialized
1760 * as g() is.
1763 TypeFunction *tf = (TypeFunction *)type;
1764 TypeFunction *tg = (TypeFunction *)g->type;
1765 size_t nfparams = Argument::dim(tf->parameters);
1766 size_t ngparams = Argument::dim(tg->parameters);
1767 MATCH match = MATCHexact;
1769 /* If both functions have a 'this' pointer, and the mods are not
1770 * the same and g's is not const, then this is less specialized.
1772 if (needThis() && g->needThis())
1774 if (tf->mod != tg->mod)
1776 if (tg->mod == MODconst)
1777 match = MATCHconst;
1778 else
1779 return MATCHnomatch;
1783 /* Create a dummy array of arguments out of the parameters to f()
1785 Expressions args;
1786 args.setDim(nfparams);
1787 for (int u = 0; u < nfparams; u++)
1789 Argument *p = Argument::getNth(tf->parameters, u);
1790 Expression *e = p->type->defaultInit();
1791 args.data[u] = e;
1794 MATCH m = (MATCH) tg->callMatch(NULL, &args);
1795 if (m)
1797 /* A variadic template is less specialized than a
1798 * non-variadic one.
1800 if (tf->varargs && !tg->varargs)
1801 goto L1; // less specialized
1803 #if LOG_LEASTAS
1804 printf(" matches %d, so is least as specialized\n", m);
1805 #endif
1806 return m;
1809 #if LOG_LEASTAS
1810 printf(" doesn't match, so is not as specialized\n");
1811 #endif
1812 return MATCHnomatch;
1815 /********************************
1816 * Labels are in a separate scope, one per function.
1819 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
1820 { Dsymbol *s;
1822 if (!labtab)
1823 labtab = new DsymbolTable(); // guess we need one
1825 s = labtab->lookup(ident);
1826 if (!s)
1828 s = new LabelDsymbol(ident);
1829 labtab->insert(s);
1831 return (LabelDsymbol *)s;
1834 /****************************************
1835 * If non-static member function that has a 'this' pointer,
1836 * return the aggregate it is a member of.
1837 * Otherwise, return NULL.
1840 AggregateDeclaration *FuncDeclaration::isThis()
1841 { AggregateDeclaration *ad;
1843 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1844 ad = NULL;
1845 if ((storage_class & STCstatic) == 0)
1847 ad = isMember2();
1849 //printf("-FuncDeclaration::isThis() %p\n", ad);
1850 return ad;
1853 AggregateDeclaration *FuncDeclaration::isMember2()
1854 { AggregateDeclaration *ad;
1856 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1857 ad = NULL;
1858 for (Dsymbol *s = this; s; s = s->parent)
1860 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1861 ad = s->isMember();
1862 if (ad)
1863 { //printf("test4\n");
1864 break;
1866 if (!s->parent ||
1867 (!s->parent->isTemplateInstance()))
1868 { //printf("test5\n");
1869 break;
1872 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1873 return ad;
1876 /*****************************************
1877 * Determine lexical level difference from 'this' to nested function 'fd'.
1878 * Error if this cannot call fd.
1879 * Returns:
1880 * 0 same level
1881 * -1 increase nesting by 1 (fd is nested within 'this')
1882 * >0 decrease nesting by number
1885 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
1886 { int level;
1887 Dsymbol *s;
1888 Dsymbol *fdparent;
1890 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1891 fdparent = fd->toParent2();
1892 if (fdparent == this)
1893 return -1;
1894 s = this;
1895 level = 0;
1896 while (fd != s && fdparent != s->toParent2())
1898 //printf("\ts = '%s'\n", s->toChars());
1899 FuncDeclaration *thisfd = s->isFuncDeclaration();
1900 if (thisfd)
1901 { if (!thisfd->isNested() && !thisfd->vthis)
1902 goto Lerr;
1904 else
1906 ClassDeclaration *thiscd = s->isClassDeclaration();
1907 if (thiscd)
1908 { if (!thiscd->isNested())
1909 goto Lerr;
1911 else
1912 goto Lerr;
1915 s = s->toParent2();
1916 assert(s);
1917 level++;
1919 return level;
1921 Lerr:
1922 error(loc, "cannot access frame of function %s", fd->toChars());
1923 return 1;
1926 void FuncDeclaration::appendExp(Expression *e)
1927 { Statement *s;
1929 s = new ExpStatement(0, e);
1930 appendState(s);
1933 void FuncDeclaration::appendState(Statement *s)
1934 { CompoundStatement *cs;
1936 if (!fbody)
1937 { Statements *a;
1939 a = new Statements();
1940 fbody = new CompoundStatement(0, a);
1942 cs = fbody->isCompoundStatement();
1943 cs->statements->push(s);
1947 int FuncDeclaration::isMain()
1949 return ident == Id::main &&
1950 linkage != LINKc && !isMember() && !isNested();
1953 int FuncDeclaration::isWinMain()
1955 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
1956 #if 0
1957 int x = ident == Id::WinMain &&
1958 linkage != LINKc && !isMember();
1959 printf("%s\n", x ? "yes" : "no");
1960 return x;
1961 #else
1962 return ident == Id::WinMain &&
1963 linkage != LINKc && !isMember();
1964 #endif
1967 int FuncDeclaration::isDllMain()
1969 return ident == Id::DllMain &&
1970 linkage != LINKc && !isMember();
1973 int FuncDeclaration::isExport()
1975 return protection == PROTexport;
1978 int FuncDeclaration::isImportedSymbol()
1980 //printf("isImportedSymbol()\n");
1981 //printf("protection = %d\n", protection);
1982 return (protection == PROTexport) && !fbody;
1985 // Determine if function goes into virtual function pointer table
1987 int FuncDeclaration::isVirtual()
1989 #if 0
1990 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1991 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
1992 printf("result is %d\n",
1993 isMember() &&
1994 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1995 toParent()->isClassDeclaration());
1996 #endif
1997 return isMember() &&
1998 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1999 toParent()->isClassDeclaration();
2002 int FuncDeclaration::isFinal()
2004 #if 0
2005 printf("FuncDeclaration::isFinal(%s)\n", toChars());
2006 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2007 printf("result is %d\n",
2008 isMember() &&
2009 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2010 toParent()->isClassDeclaration());
2011 #endif
2012 ClassDeclaration *cd;
2013 return isMember() &&
2014 (Declaration::isFinal() ||
2015 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2018 int FuncDeclaration::isAbstract()
2020 return storage_class & STCabstract;
2023 int FuncDeclaration::isCodeseg()
2025 return TRUE; // functions are always in the code segment
2028 int FuncDeclaration::isOverloadable()
2030 return 1; // functions can be overloaded
2033 // Determine if function needs
2034 // a static frame pointer to its lexically enclosing function
2036 int FuncDeclaration::isNested()
2038 //if (!toParent())
2039 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2040 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2041 return ((storage_class & STCstatic) == 0) &&
2042 (toParent2()->isFuncDeclaration() != NULL);
2045 int FuncDeclaration::needThis()
2047 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2048 int i = isThis() != NULL;
2049 //printf("\t%d\n", i);
2050 if (!i && isFuncAliasDeclaration())
2051 i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
2052 return i;
2055 int FuncDeclaration::addPreInvariant()
2057 AggregateDeclaration *ad = isThis();
2058 return (ad &&
2059 //ad->isClassDeclaration() &&
2060 global.params.useInvariants &&
2061 (protection == PROTpublic || protection == PROTexport) &&
2062 !naked &&
2063 ident != Id::cpctor);
2066 int FuncDeclaration::addPostInvariant()
2068 AggregateDeclaration *ad = isThis();
2069 return (ad &&
2070 ad->inv &&
2071 //ad->isClassDeclaration() &&
2072 global.params.useInvariants &&
2073 (protection == PROTpublic || protection == PROTexport) &&
2074 !naked &&
2075 ident != Id::cpctor);
2078 /**********************************
2079 * Generate a FuncDeclaration for a runtime library function.
2082 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name,
2083 Type *t1, Type *t2, Type *t3)
2085 return genCfunc(treturn, Lexer::idPool(name), t1, t2, t3);
2088 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id,
2089 Type *t1, Type *t2, Type *t3)
2091 FuncDeclaration *fd;
2092 TypeFunction *tf;
2093 Dsymbol *s;
2094 static DsymbolTable *st = NULL;
2096 //printf("genCfunc(name = '%s')\n", id->toChars());
2097 //printf("treturn\n\t"); treturn->print();
2099 // See if already in table
2100 if (!st)
2101 st = new DsymbolTable();
2102 s = st->lookup(id);
2103 if (s)
2105 fd = s->isFuncDeclaration();
2106 assert(fd);
2107 assert(fd->type->nextOf()->equals(treturn));
2109 else
2111 Arguments * args = 0;
2112 if (t1) {
2113 args = new Arguments;
2114 args->push(new Argument(STCin,t1,0,0));
2115 if (t2)
2117 args->push(new Argument(STCin,t2,0,0));
2118 if (t3)
2119 args->push(new Argument(STCin,t3,0,0));
2123 tf = new TypeFunction(args, treturn, 0, LINKc);
2124 fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2125 fd->protection = PROTpublic;
2126 fd->linkage = LINKc;
2128 st->insert(fd);
2130 return fd;
2133 char *FuncDeclaration::kind()
2135 return "function";
2138 /*******************************
2139 * Look at all the variables in this function that are referenced
2140 * by nested functions, and determine if a closure needs to be
2141 * created for them.
2144 #if V2
2145 int FuncDeclaration::needsClosure()
2147 /* Need a closure for all the closureVars[] if any of the
2148 * closureVars[] are accessed by a
2149 * function that escapes the scope of this function.
2150 * We take the conservative approach and decide that any function that:
2151 * 1) is a virtual function
2152 * 2) has its address taken
2153 * 3) has a parent that escapes
2155 * Note that since a non-virtual function can be called by
2156 * a virtual one, if that non-virtual function accesses a closure
2157 * var, the closure still has to be taken. Hence, we check for isThis()
2158 * instead of isVirtual(). (thanks to David Friedman)
2161 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2162 for (int i = 0; i < closureVars.dim; i++)
2163 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
2164 assert(v->isVarDeclaration());
2165 //printf("\tv = %s\n", v->toChars());
2167 for (int j = 0; j < v->nestedrefs.dim; j++)
2168 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
2169 assert(f != this);
2171 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2172 if (f->isThis() || f->tookAddressOf)
2173 goto Lyes; // assume f escapes this function's scope
2175 // Look to see if any parents of f that are below this escape
2176 for (Dsymbol *s = f->parent; s != this; s = s->parent)
2178 f = s->isFuncDeclaration();
2179 if (f && (f->isThis() || f->tookAddressOf))
2180 goto Lyes;
2184 return 0;
2186 Lyes:
2187 //printf("\tneeds closure\n");
2188 return 1;
2190 #endif
2192 /****************************** FuncAliasDeclaration ************************/
2194 // Used as a way to import a set of functions from another scope into this one.
2196 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2197 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2198 (enum STC)funcalias->storage_class, funcalias->type)
2200 assert(funcalias != this);
2201 this->funcalias = funcalias;
2204 char *FuncAliasDeclaration::kind()
2206 return "function alias";
2210 /****************************** FuncLiteralDeclaration ************************/
2212 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2213 enum TOK tok, ForeachStatement *fes)
2214 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2216 char *id;
2218 if (fes)
2219 id = "__foreachbody";
2220 else if (tok == TOKdelegate)
2221 id = "__dgliteral";
2222 else
2223 id = "__funcliteral";
2224 this->ident = Identifier::generateId(id);
2225 this->tok = tok;
2226 this->fes = fes;
2227 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2230 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2232 FuncLiteralDeclaration *f;
2234 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2235 if (s)
2236 f = (FuncLiteralDeclaration *)s;
2237 else
2238 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2239 FuncDeclaration::syntaxCopy(f);
2240 return f;
2243 int FuncLiteralDeclaration::isNested()
2245 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2246 return (tok == TOKdelegate);
2249 char *FuncLiteralDeclaration::kind()
2251 // GCC requires the (char*) casts
2252 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
2255 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2257 static Identifier *idfunc;
2258 static Identifier *iddel;
2260 if (!idfunc)
2261 idfunc = new Identifier("function", 0);
2262 if (!iddel)
2263 iddel = new Identifier("delegate", 0);
2265 type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
2266 bodyToCBuffer(buf, hgs);
2270 /********************************* CtorDeclaration ****************************/
2272 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2273 : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
2275 this->arguments = arguments;
2276 this->varargs = varargs;
2277 //printf("CtorDeclaration() %s\n", toChars());
2280 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2282 CtorDeclaration *f;
2284 f = new CtorDeclaration(loc, endloc, NULL, varargs);
2286 f->outId = outId;
2287 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2288 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
2289 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
2290 assert(!fthrows); // deprecated
2292 f->arguments = Argument::arraySyntaxCopy(arguments);
2293 return f;
2297 void CtorDeclaration::semantic(Scope *sc)
2299 ClassDeclaration *cd;
2300 Type *tret;
2302 //printf("CtorDeclaration::semantic()\n");
2303 if (type)
2304 return;
2306 sc = sc->push();
2307 sc->stc &= ~STCstatic; // not a static constructor
2309 parent = sc->parent;
2310 Dsymbol *parent = toParent();
2311 cd = parent->isClassDeclaration();
2312 if (!cd)
2314 error("constructors are only for class definitions");
2315 tret = Type::tvoid;
2317 else
2319 tret = cd->type; //->referenceTo();
2321 for (int i = 0; i < cd->fields.dim; i++)
2323 VarDeclaration *vd = (VarDeclaration *) cd->fields.data[i];
2324 if (vd->storage_class & STCinject)
2326 if (!arguments)
2327 arguments = new Arguments();
2328 Argument *a = new Argument(vd->storage_class, vd->type, vd->ident, 0);
2329 // BUG: We don't really want these arguments in scope...
2330 arguments->push(a);
2332 Statement *assign = new ExpStatement(loc, new AssignExp(loc,
2333 new DotIdExp(loc, new ThisExp(loc), a->ident),
2334 new IdentifierExp(loc, a->ident)));
2335 if (fbody)
2336 fbody = new CompoundStatement(loc, assign, fbody);
2337 else
2338 fbody = assign;
2343 type = new TypeFunction(arguments, tret, varargs, LINKd);
2345 sc->flags |= SCOPEctor;
2346 type = type->semantic(loc, sc);
2347 sc->flags &= ~SCOPEctor;
2349 // Append:
2350 // return this;
2351 // to the function body
2352 if (fbody)
2353 { Expression *e;
2354 Statement *s;
2356 e = new ThisExp(0);
2357 s = new ReturnStatement(0, e);
2358 fbody = new CompoundStatement(0, fbody, s);
2361 FuncDeclaration::semantic(sc);
2363 sc->pop();
2365 // See if it's the default constructor
2366 if (cd && varargs == 0 && Argument::dim(arguments) == 0)
2367 cd->defaultCtor = this;
2370 char *CtorDeclaration::kind()
2372 return "constructor";
2375 char *CtorDeclaration::toChars()
2377 return "this";
2380 int CtorDeclaration::isVirtual()
2382 return FALSE;
2385 int CtorDeclaration::addPreInvariant()
2387 return FALSE;
2390 int CtorDeclaration::addPostInvariant()
2392 return (vthis && global.params.useInvariants);
2396 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2398 buf->writestring("this");
2399 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2400 bodyToCBuffer(buf, hgs);
2403 /********************************* PostBlitDeclaration ****************************/
2405 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
2406 : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
2410 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
2411 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2415 Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
2417 assert(!s);
2418 PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
2419 return FuncDeclaration::syntaxCopy(dd);
2423 void PostBlitDeclaration::semantic(Scope *sc)
2425 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2426 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2427 parent = sc->parent;
2428 Dsymbol *parent = toParent();
2429 StructDeclaration *ad = parent->isStructDeclaration();
2430 if (!ad)
2432 error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2434 else if (ident == Id::_postblit)
2435 ad->postblits.push(this);
2436 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2438 sc = sc->push();
2439 sc->stc &= ~STCstatic; // not static
2440 sc->linkage = LINKd;
2442 FuncDeclaration::semantic(sc);
2444 sc->pop();
2447 int PostBlitDeclaration::overloadInsert(Dsymbol *s)
2449 return FALSE; // cannot overload postblits
2452 int PostBlitDeclaration::addPreInvariant()
2454 return FALSE;
2457 int PostBlitDeclaration::addPostInvariant()
2459 return (vthis && global.params.useInvariants);
2462 int PostBlitDeclaration::isVirtual()
2464 return FALSE;
2467 void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2469 if (hgs->hdrgen)
2470 return;
2471 buf->writestring("=this()");
2472 bodyToCBuffer(buf, hgs);
2475 /********************************* DtorDeclaration ****************************/
2477 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
2478 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
2482 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
2483 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2487 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
2489 assert(!s);
2490 DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
2491 return FuncDeclaration::syntaxCopy(dd);
2495 void DtorDeclaration::semantic(Scope *sc)
2497 //printf("DtorDeclaration::semantic() %s\n", toChars());
2498 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2499 parent = sc->parent;
2500 Dsymbol *parent = toParent();
2501 AggregateDeclaration *ad = parent->isAggregateDeclaration();
2502 if (!ad)
2504 error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2506 else if (ident == Id::dtor)
2507 ad->dtors.push(this);
2508 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2510 sc = sc->push();
2511 sc->stc &= ~STCstatic; // not a static destructor
2512 sc->linkage = LINKd;
2514 FuncDeclaration::semantic(sc);
2516 sc->pop();
2519 int DtorDeclaration::overloadInsert(Dsymbol *s)
2521 return FALSE; // cannot overload destructors
2524 int DtorDeclaration::addPreInvariant()
2526 return (vthis && global.params.useInvariants);
2529 int DtorDeclaration::addPostInvariant()
2531 return FALSE;
2534 int DtorDeclaration::isVirtual()
2536 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2537 * but doing so will require recompiling everything.
2539 #if BREAKABI
2540 return FALSE;
2541 #else
2542 return FuncDeclaration::isVirtual();
2543 #endif
2546 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2548 if (hgs->hdrgen)
2549 return;
2550 buf->writestring("~this()");
2551 bodyToCBuffer(buf, hgs);
2554 /********************************* StaticCtorDeclaration ****************************/
2556 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
2557 : FuncDeclaration(loc, endloc,
2558 Identifier::generateId("_staticCtor"), STCstatic, NULL)
2562 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
2564 StaticCtorDeclaration *scd;
2566 assert(!s);
2567 scd = new StaticCtorDeclaration(loc, endloc);
2568 return FuncDeclaration::syntaxCopy(scd);
2572 void StaticCtorDeclaration::semantic(Scope *sc)
2574 //printf("StaticCtorDeclaration::semantic()\n");
2576 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2578 FuncDeclaration::semantic(sc);
2580 // We're going to need ModuleInfo
2581 Module *m = getModule();
2582 if (!m)
2583 m = sc->module;
2584 if (m)
2585 { m->needmoduleinfo = 1;
2586 #ifdef IN_GCC
2587 m->strictlyneedmoduleinfo = 1;
2588 #endif
2592 AggregateDeclaration *StaticCtorDeclaration::isThis()
2594 return NULL;
2597 int StaticCtorDeclaration::isStaticConstructor()
2599 return TRUE;
2602 int StaticCtorDeclaration::isVirtual()
2604 return FALSE;
2607 int StaticCtorDeclaration::addPreInvariant()
2609 return FALSE;
2612 int StaticCtorDeclaration::addPostInvariant()
2614 return FALSE;
2617 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2619 if (hgs->hdrgen)
2620 { buf->writestring("static this();\n");
2621 return;
2623 buf->writestring("static this()");
2624 bodyToCBuffer(buf, hgs);
2627 /********************************* StaticDtorDeclaration ****************************/
2629 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
2630 : FuncDeclaration(loc, endloc,
2631 Identifier::generateId("_staticDtor"), STCstatic, NULL)
2635 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
2637 StaticDtorDeclaration *sdd;
2639 assert(!s);
2640 sdd = new StaticDtorDeclaration(loc, endloc);
2641 return FuncDeclaration::syntaxCopy(sdd);
2645 void StaticDtorDeclaration::semantic(Scope *sc)
2647 ClassDeclaration *cd;
2648 Type *tret;
2650 cd = sc->scopesym->isClassDeclaration();
2651 if (!cd)
2654 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2656 FuncDeclaration::semantic(sc);
2658 // We're going to need ModuleInfo
2659 Module *m = getModule();
2660 if (!m)
2661 m = sc->module;
2662 if (m)
2663 { m->needmoduleinfo = 1;
2664 #ifdef IN_GCC
2665 m->strictlyneedmoduleinfo = 1;
2666 #endif
2670 AggregateDeclaration *StaticDtorDeclaration::isThis()
2672 return NULL;
2675 int StaticDtorDeclaration::isStaticDestructor()
2677 return TRUE;
2680 int StaticDtorDeclaration::isVirtual()
2682 return FALSE;
2685 int StaticDtorDeclaration::addPreInvariant()
2687 return FALSE;
2690 int StaticDtorDeclaration::addPostInvariant()
2692 return FALSE;
2695 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2697 if (hgs->hdrgen)
2698 return;
2699 buf->writestring("static ~this()");
2700 bodyToCBuffer(buf, hgs);
2703 /********************************* InvariantDeclaration ****************************/
2705 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
2706 : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
2710 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
2712 InvariantDeclaration *id;
2714 assert(!s);
2715 id = new InvariantDeclaration(loc, endloc);
2716 FuncDeclaration::syntaxCopy(id);
2717 return id;
2721 void InvariantDeclaration::semantic(Scope *sc)
2723 AggregateDeclaration *ad;
2724 Type *tret;
2726 parent = sc->parent;
2727 Dsymbol *parent = toParent();
2728 ad = parent->isAggregateDeclaration();
2729 if (!ad)
2731 error("invariants only are for struct/union/class definitions");
2732 return;
2734 else if (ad->inv && ad->inv != this)
2736 error("more than one invariant for %s", ad->toChars());
2738 ad->inv = this;
2739 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2741 sc = sc->push();
2742 sc->stc &= ~STCstatic; // not a static invariant
2743 sc->incontract++;
2744 sc->linkage = LINKd;
2746 FuncDeclaration::semantic(sc);
2748 sc->pop();
2751 int InvariantDeclaration::isVirtual()
2753 return FALSE;
2756 int InvariantDeclaration::addPreInvariant()
2758 return FALSE;
2761 int InvariantDeclaration::addPostInvariant()
2763 return FALSE;
2766 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2768 if (hgs->hdrgen)
2769 return;
2770 buf->writestring("invariant");
2771 bodyToCBuffer(buf, hgs);
2775 /********************************* UnitTestDeclaration ****************************/
2777 /*******************************
2778 * Generate unique unittest function Id so we can have multiple
2779 * instances per module.
2782 static Identifier *unitTestId()
2784 return Lexer::uniqueId("__unittest");
2787 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
2788 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
2792 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
2794 UnitTestDeclaration *utd;
2796 assert(!s);
2797 utd = new UnitTestDeclaration(loc, endloc);
2798 return FuncDeclaration::syntaxCopy(utd);
2802 void UnitTestDeclaration::semantic(Scope *sc)
2804 if (global.params.useUnitTests)
2806 Type *tret;
2808 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2809 FuncDeclaration::semantic(sc);
2812 // We're going to need ModuleInfo even if the unit tests are not
2813 // compiled in, because other modules may import this module and refer
2814 // to this ModuleInfo.
2815 Module *m = getModule();
2816 if (!m)
2817 m = sc->module;
2818 if (m)
2819 m->needmoduleinfo = 1;
2822 AggregateDeclaration *UnitTestDeclaration::isThis()
2824 return NULL;
2827 int UnitTestDeclaration::isVirtual()
2829 return FALSE;
2832 int UnitTestDeclaration::addPreInvariant()
2834 return FALSE;
2837 int UnitTestDeclaration::addPostInvariant()
2839 return FALSE;
2842 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2844 if (hgs->hdrgen)
2845 return;
2846 buf->writestring("unittest");
2847 bodyToCBuffer(buf, hgs);
2850 /********************************* NewDeclaration ****************************/
2852 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2853 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
2855 this->arguments = arguments;
2856 this->varargs = varargs;
2859 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
2861 NewDeclaration *f;
2863 f = new NewDeclaration(loc, endloc, NULL, varargs);
2865 FuncDeclaration::syntaxCopy(f);
2867 f->arguments = Argument::arraySyntaxCopy(arguments);
2869 return f;
2873 void NewDeclaration::semantic(Scope *sc)
2875 ClassDeclaration *cd;
2876 Type *tret;
2878 //printf("NewDeclaration::semantic()\n");
2880 parent = sc->parent;
2881 Dsymbol *parent = toParent();
2882 cd = parent->isClassDeclaration();
2883 if (!cd && !parent->isStructDeclaration())
2885 error("new allocators only are for class or struct definitions");
2887 tret = Type::tvoid->pointerTo();
2888 type = new TypeFunction(arguments, tret, varargs, LINKd);
2890 type = type->semantic(loc, sc);
2891 assert(type->ty == Tfunction);
2893 // Check that there is at least one argument of type uint
2894 TypeFunction *tf = (TypeFunction *)type;
2895 if (Argument::dim(tf->parameters) < 1)
2897 error("at least one argument of type uint expected");
2899 else
2901 Argument *a = Argument::getNth(tf->parameters, 0);
2902 if (!a->type->equals(Type::tuns32) &&
2903 (! global.params.isX86_64 || !a->type->equals(Type::tuns64)))
2904 error("first argument must be type uint, not %s", a->type->toChars());
2907 FuncDeclaration::semantic(sc);
2910 char *NewDeclaration::kind()
2912 return "allocator";
2915 int NewDeclaration::isVirtual()
2917 return FALSE;
2920 int NewDeclaration::addPreInvariant()
2922 return FALSE;
2925 int NewDeclaration::addPostInvariant()
2927 return FALSE;
2930 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2932 buf->writestring("new");
2933 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2934 bodyToCBuffer(buf, hgs);
2938 /********************************* DeleteDeclaration ****************************/
2940 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
2941 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
2943 this->arguments = arguments;
2946 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
2948 DeleteDeclaration *f;
2950 f = new DeleteDeclaration(loc, endloc, NULL);
2952 FuncDeclaration::syntaxCopy(f);
2954 f->arguments = Argument::arraySyntaxCopy(arguments);
2956 return f;
2960 void DeleteDeclaration::semantic(Scope *sc)
2962 ClassDeclaration *cd;
2964 //printf("DeleteDeclaration::semantic()\n");
2966 parent = sc->parent;
2967 Dsymbol *parent = toParent();
2968 cd = parent->isClassDeclaration();
2969 if (!cd && !parent->isStructDeclaration())
2971 error("new allocators only are for class or struct definitions");
2973 type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
2975 type = type->semantic(loc, sc);
2976 assert(type->ty == Tfunction);
2978 // Check that there is only one argument of type void*
2979 TypeFunction *tf = (TypeFunction *)type;
2980 if (Argument::dim(tf->parameters) != 1)
2982 error("one argument of type void* expected");
2984 else
2986 Argument *a = Argument::getNth(tf->parameters, 0);
2987 if (!a->type->equals(Type::tvoid->pointerTo()))
2988 error("one argument of type void* expected, not %s", a->type->toChars());
2991 FuncDeclaration::semantic(sc);
2994 char *DeleteDeclaration::kind()
2996 return "deallocator";
2999 int DeleteDeclaration::isDelete()
3001 return TRUE;
3004 int DeleteDeclaration::isVirtual()
3006 return FALSE;
3009 int DeleteDeclaration::addPreInvariant()
3011 return FALSE;
3014 int DeleteDeclaration::addPostInvariant()
3016 return FALSE;
3019 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3021 buf->writestring("delete");
3022 Argument::argsToCBuffer(buf, hgs, arguments, 0);
3023 bodyToCBuffer(buf, hgs);