Allow returning something of type void in a function that returns void
[delight/core.git] / dmd2 / func.c
blob66fdb1cb35a8d1bc5be19ae70edb5fd2ea71af04
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))
1034 error(v->loc,
1035 "missing initializer for non-null field %s",
1036 v->toChars());
1042 if (!(sc2->callSuper & CSXany_ctor) &&
1043 cd->baseClass && cd->baseClass->ctor)
1045 sc2->callSuper = 0;
1047 // Insert implicit super() at start of fbody
1048 Expression *e1 = new SuperExp(0);
1049 Expression *e = new CallExp(0, e1);
1051 unsigned errors = global.errors;
1052 global.gag++;
1053 e = e->semantic(sc2);
1054 global.gag--;
1055 if (errors != global.errors)
1056 error("no match for implicit super() call in constructor");
1058 Statement *s = new ExpStatement(0, e);
1059 fbody = new CompoundStatement(0, s, fbody);
1062 else if (fes)
1063 { // For foreach(){} body, append a return 0;
1064 Expression *e = new IntegerExp(0);
1065 Statement *s = new ReturnStatement(0, e);
1066 fbody = new CompoundStatement(0, fbody, s);
1067 assert(!returnLabel);
1069 else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1070 error("expected to return a value of type %s", type->nextOf()->toChars());
1071 else if (!inlineAsm)
1073 int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
1074 //int offend = fbody ? fbody->fallOffEnd() : TRUE;
1076 if (type->nextOf()->ty == Tvoid)
1078 if (offend && isMain())
1079 { // Add a return 0; statement
1080 Statement *s = new ReturnStatement(0, new IntegerExp(0));
1081 fbody = new CompoundStatement(0, fbody, s);
1084 else
1086 if (offend)
1087 { Expression *e;
1089 if (global.params.warnings)
1090 { fprintf(stdmsg, "warning - ");
1091 error("no return at end of function");
1094 if (global.params.useAssert &&
1095 !global.params.useInline)
1096 { /* Add an assert(0, msg); where the missing return
1097 * should be.
1099 e = new AssertExp(
1100 endloc,
1101 new IntegerExp(0),
1102 new StringExp(loc, "missing return expression")
1105 else
1106 e = new HaltExp(endloc);
1107 e = new CommaExp(0, e, type->nextOf()->defaultInit());
1108 e = e->semantic(sc2);
1109 Statement *s = new ExpStatement(0, e);
1110 fbody = new CompoundStatement(0, fbody, s);
1117 Statements *a = new Statements();
1119 // Merge in initialization of 'out' parameters
1120 if (parameters)
1121 { for (size_t i = 0; i < parameters->dim; i++)
1123 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1124 if (v->storage_class & STCout)
1126 assert(v->init);
1127 ExpInitializer *ie = v->init->isExpInitializer();
1128 assert(ie);
1129 a->push(new ExpStatement(0, ie->exp));
1134 if (argptr)
1135 { // Initialize _argptr to point past non-variadic arg
1136 #if IN_GCC
1137 // Handled in FuncDeclaration::toObjFile
1138 v_argptr = argptr;
1139 v_argptr->init = new VoidInitializer(loc);
1140 #else
1141 Expression *e1;
1142 Expression *e;
1143 Type *t = argptr->type;
1144 VarDeclaration *p;
1145 unsigned offset;
1147 e1 = new VarExp(0, argptr);
1148 if (parameters && parameters->dim)
1149 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1150 else
1151 p = v_arguments; // last parameter is _arguments[]
1152 offset = p->type->size();
1153 offset = (offset + 3) & ~3; // assume stack aligns on 4
1154 e = new SymOffExp(0, p, offset);
1155 e = new AssignExp(0, e1, e);
1156 e->type = t;
1157 a->push(new ExpStatement(0, e));
1158 #endif
1161 if (_arguments)
1163 #if IN_GCC
1164 v_arguments_var = _arguments;
1165 v_arguments_var->init = new VoidInitializer(loc);
1166 #endif
1167 /* Advance to elements[] member of TypeInfo_Tuple with:
1168 * _arguments = v_arguments.elements;
1170 Expression *e = new VarExp(0, v_arguments);
1171 e = new DotIdExp(0, e, Id::elements);
1172 Expression *e1 = new VarExp(0, _arguments);
1173 e = new AssignExp(0, e1, e);
1174 e->op = TOKconstruct;
1175 e = e->semantic(sc);
1176 a->push(new ExpStatement(0, e));
1179 // Merge contracts together with body into one compound statement
1181 #ifdef _DH
1182 if (frequire && global.params.useIn)
1183 { frequire->incontract = 1;
1184 a->push(frequire);
1186 #else
1187 if (frequire && global.params.useIn)
1188 a->push(frequire);
1189 #endif
1191 // Precondition invariant
1192 if (addPreInvariant())
1194 Expression *e = NULL;
1195 if (isDtorDeclaration())
1197 // Call invariant directly only if it exists
1198 InvariantDeclaration *inv = ad->inv;
1199 ClassDeclaration *cd = ad->isClassDeclaration();
1201 while (!inv && cd)
1203 cd = cd->baseClass;
1204 if (!cd)
1205 break;
1206 inv = cd->inv;
1208 if (inv)
1210 e = new DsymbolExp(0, inv);
1211 e = new CallExp(0, e);
1212 e = e->semantic(sc2);
1215 else
1216 { // Call invariant virtually
1217 ThisExp *v = new ThisExp(0);
1218 v->type = vthis->type;
1219 Expression *se = new StringExp(0, "null this");
1220 se = se->semantic(sc);
1221 se->type = Type::tchar->arrayOf();
1222 e = new AssertExp(loc, v, se);
1224 if (e)
1226 ExpStatement *s = new ExpStatement(0, e);
1227 a->push(s);
1231 if (fbody)
1232 a->push(fbody);
1234 if (fensure)
1236 a->push(returnLabel->statement);
1238 if (type->nextOf()->ty != Tvoid)
1240 // Create: return vresult;
1241 assert(vresult);
1242 Expression *e = new VarExp(0, vresult);
1243 if (tintro)
1244 { e = e->implicitCastTo(sc, tintro->nextOf());
1245 e = e->semantic(sc);
1247 ReturnStatement *s = new ReturnStatement(0, e);
1248 a->push(s);
1252 fbody = new CompoundStatement(0, a);
1254 /* Append destructor calls for parameters as finally blocks.
1256 if (parameters)
1257 { for (size_t i = 0; i < parameters->dim; i++)
1259 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1261 if (v->storage_class & (STCref | STCout))
1262 continue;
1264 /* Don't do this for static arrays, since static
1265 * arrays are called by reference. Remove this
1266 * when we change them to call by value.
1268 if (v->type->toBasetype()->ty == Tsarray)
1269 continue;
1271 Expression *e = v->callAutoDtor(sc);
1272 if (e)
1273 { Statement *s = new ExpStatement(0, e);
1274 s = s->semantic(sc);
1275 if (fbody->blockExit() == BEfallthru)
1276 fbody = new CompoundStatement(0, fbody, s);
1277 else
1278 fbody = new TryFinallyStatement(0, fbody, s);
1284 sc2->callSuper = 0;
1285 sc2->pop();
1287 semanticRun = 2;
1290 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1292 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1294 type->toCBuffer(buf, ident, hgs);
1295 bodyToCBuffer(buf, hgs);
1299 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1301 if (fbody &&
1302 (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1304 { buf->writenl();
1306 // in{}
1307 if (frequire)
1308 { buf->writestring("in");
1309 buf->writenl();
1310 frequire->toCBuffer(buf, hgs);
1313 // out{}
1314 if (fensure)
1315 { buf->writestring("out");
1316 if (outId)
1317 { buf->writebyte('(');
1318 buf->writestring(outId->toChars());
1319 buf->writebyte(')');
1321 buf->writenl();
1322 fensure->toCBuffer(buf, hgs);
1325 if (frequire || fensure)
1326 { buf->writestring("body");
1327 buf->writenl();
1330 buf->writebyte('{');
1331 buf->writenl();
1332 fbody->toCBuffer(buf, hgs);
1333 buf->writebyte('}');
1334 buf->writenl();
1336 else
1337 { buf->writeByte(';');
1338 buf->writenl();
1342 /****************************************************
1343 * Determine if 'this' overrides fd.
1344 * Return !=0 if it does.
1347 int FuncDeclaration::overrides(FuncDeclaration *fd)
1348 { int result = 0;
1350 if (fd->ident == ident)
1352 int cov = type->covariant(fd->type);
1353 if (cov)
1354 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1355 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1357 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1358 result = 1;
1361 return result;
1364 /*************************************************
1365 * Find index of function in vtbl[0..dim] that
1366 * this function overrides.
1367 * Returns:
1368 * -1 didn't find one
1369 * -2 can't determine because of forward references
1372 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
1374 for (int vi = 0; vi < dim; vi++)
1376 FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
1377 if (fdv && fdv->ident == ident)
1379 int cov = type->covariant(fdv->type);
1380 //printf("\tbaseclass cov = %d\n", cov);
1381 switch (cov)
1383 case 0: // types are distinct
1384 break;
1386 case 1:
1387 return vi;
1389 case 2:
1390 //type->print();
1391 //fdv->type->print();
1392 //printf("%s %s\n", type->deco, fdv->type->deco);
1393 error("of type %s overrides but is not covariant with %s of type %s",
1394 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
1395 break;
1397 case 3:
1398 return -2; // forward references
1400 default:
1401 assert(0);
1405 return -1;
1408 /****************************************************
1409 * Overload this FuncDeclaration with the new one f.
1410 * Return !=0 if successful; i.e. no conflict.
1413 int FuncDeclaration::overloadInsert(Dsymbol *s)
1415 FuncDeclaration *f;
1416 AliasDeclaration *a;
1418 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1419 a = s->isAliasDeclaration();
1420 if (a)
1422 if (overnext)
1423 return overnext->overloadInsert(a);
1424 if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1426 //printf("\ta = '%s'\n", a->type->toChars());
1427 return FALSE;
1429 overnext = a;
1430 //printf("\ttrue: no conflict\n");
1431 return TRUE;
1433 f = s->isFuncDeclaration();
1434 if (!f)
1435 return FALSE;
1437 #if 0
1438 /* Disable this check because:
1439 * const void foo();
1440 * semantic() isn't run yet on foo(), so the const hasn't been
1441 * applied yet.
1443 if (type)
1444 { printf("type = %s\n", type->toChars());
1445 printf("f->type = %s\n", f->type->toChars());
1447 if (type && f->type && // can be NULL for overloaded constructors
1448 f->type->covariant(type) &&
1449 f->type->mod == type->mod &&
1450 !isFuncAliasDeclaration())
1452 //printf("\tfalse: conflict %s\n", kind());
1453 return FALSE;
1455 #endif
1457 if (overnext)
1458 return overnext->overloadInsert(f);
1459 overnext = f;
1460 //printf("\ttrue: no conflict\n");
1461 return TRUE;
1464 /***************************************************
1465 * Visit each overloaded function in turn, and call
1466 * (*fp)(param, f) on it.
1467 * Exit when no more, or (*fp)(param, f) returns 1.
1468 * Returns:
1469 * 0 continue
1470 * 1 done
1473 int overloadApply(FuncDeclaration *fstart,
1474 int (*fp)(void *, FuncDeclaration *),
1475 void *param)
1477 FuncDeclaration *f;
1478 Declaration *d;
1479 Declaration *next;
1481 for (d = fstart; d; d = next)
1482 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1484 if (fa)
1486 if (overloadApply(fa->funcalias, fp, param))
1487 return 1;
1488 next = fa->overnext;
1490 else
1492 AliasDeclaration *a = d->isAliasDeclaration();
1494 if (a)
1496 Dsymbol *s = a->toAlias();
1497 next = s->isDeclaration();
1498 if (next == a)
1499 break;
1500 if (next == fstart)
1501 break;
1503 else
1505 f = d->isFuncDeclaration();
1506 if (!f)
1507 { d->error("is aliased to a function");
1508 break; // BUG: should print error message?
1510 if ((*fp)(param, f))
1511 return 1;
1513 next = f->overnext;
1517 return 0;
1520 /********************************************
1521 * If there are no overloads of function f, return that function,
1522 * otherwise return NULL.
1525 static int fpunique(void *param, FuncDeclaration *f)
1526 { FuncDeclaration **pf = (FuncDeclaration **)param;
1528 if (*pf)
1529 { *pf = NULL;
1530 return 1; // ambiguous, done
1532 else
1533 { *pf = f;
1534 return 0;
1538 FuncDeclaration *FuncDeclaration::isUnique()
1539 { FuncDeclaration *result = NULL;
1541 overloadApply(this, &fpunique, &result);
1542 return result;
1545 /********************************************
1546 * Find function in overload list that exactly matches t.
1549 struct Param1
1551 Type *t; // type to match
1552 FuncDeclaration *f; // return value
1555 int fp1(void *param, FuncDeclaration *f)
1556 { Param1 *p = (Param1 *)param;
1557 Type *t = p->t;
1559 if (t->equals(f->type))
1560 { p->f = f;
1561 return 1;
1564 #if V2
1565 /* Allow covariant matches, if it's just a const conversion
1566 * of the return type
1568 if (t->ty == Tfunction)
1569 { TypeFunction *tf = (TypeFunction *)f->type;
1570 if (tf->covariant(t) == 1 &&
1571 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
1573 p->f = f;
1574 return 1;
1577 #endif
1578 return 0;
1581 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1583 Param1 p;
1584 p.t = t;
1585 p.f = NULL;
1586 overloadApply(this, &fp1, &p);
1587 return p.f;
1591 /********************************************
1592 * Decide which function matches the arguments best.
1595 struct Param2
1597 Match *m;
1598 Expression *ethis;
1599 Expressions *arguments;
1602 int fp2(void *param, FuncDeclaration *f)
1603 { Param2 *p = (Param2 *)param;
1604 Match *m = p->m;
1605 Expressions *arguments = p->arguments;
1606 MATCH match;
1608 if (f != m->lastf) // skip duplicates
1610 m->anyf = f;
1611 TypeFunction *tf = (TypeFunction *)f->type;
1612 match = (MATCH) tf->callMatch(f->needThis() ? p->ethis : NULL, arguments);
1613 //printf("match = %d\n", match);
1614 if (match != MATCHnomatch)
1616 if (match > m->last)
1617 goto LfIsBetter;
1619 if (match < m->last)
1620 goto LlastIsBetter;
1622 /* See if one of the matches overrides the other.
1624 if (m->lastf->overrides(f))
1625 goto LlastIsBetter;
1626 else if (f->overrides(m->lastf))
1627 goto LfIsBetter;
1629 /* Try to disambiguate using template-style partial ordering rules.
1630 * In essence, if f() and g() are ambiguous, if f() can call g(),
1631 * but g() cannot call f(), then pick f().
1632 * This is because f() is "more specialized."
1635 MATCH c1 = f->leastAsSpecialized(m->lastf);
1636 MATCH c2 = m->lastf->leastAsSpecialized(f);
1637 if (c1 > c2)
1638 goto LfIsBetter;
1639 if (c1 < c2)
1640 goto LlastIsBetter;
1643 Lambiguous:
1644 m->nextf = f;
1645 m->count++;
1646 return 0;
1648 LfIsBetter:
1649 m->last = match;
1650 m->lastf = f;
1651 m->count = 1;
1652 return 0;
1654 LlastIsBetter:
1655 return 0;
1658 return 0;
1661 void overloadResolveX(Match *m, FuncDeclaration *fstart,
1662 Expression *ethis, Expressions *arguments)
1664 Param2 p;
1665 p.m = m;
1666 p.ethis = ethis;
1667 p.arguments = arguments;
1668 overloadApply(fstart, &fp2, &p);
1672 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags)
1674 TypeFunction *tf;
1675 Match m;
1677 #if 0
1678 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1679 if (arguments)
1680 { int i;
1682 for (i = 0; i < arguments->dim; i++)
1683 { Expression *arg;
1685 arg = (Expression *)arguments->data[i];
1686 assert(arg->type);
1687 printf("\t%s: ", arg->toChars());
1688 arg->type->print();
1691 #endif
1693 memset(&m, 0, sizeof(m));
1694 m.last = MATCHnomatch;
1695 overloadResolveX(&m, this, ethis, arguments);
1697 if (m.count == 1) // exactly one match
1699 return m.lastf;
1701 else
1703 OutBuffer buf;
1705 if (arguments)
1707 HdrGenState hgs;
1709 argExpTypesToCBuffer(&buf, arguments, &hgs);
1712 if (m.last == MATCHnomatch)
1714 if (flags & 1) // if do not print error messages
1715 return NULL; // no match
1717 tf = (TypeFunction *)type;
1719 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1720 error(loc, "%s does not match parameter types (%s)",
1721 Argument::argsTypesToChars(tf->parameters, tf->varargs),
1722 buf.toChars());
1723 return m.anyf; // as long as it's not a FuncAliasDeclaration
1725 else
1727 #if 1
1728 TypeFunction *t1 = (TypeFunction *)m.lastf->type;
1729 TypeFunction *t2 = (TypeFunction *)m.nextf->type;
1731 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1732 buf.toChars(),
1733 m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
1734 m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
1735 #else
1736 error(loc, "overloads %s and %s both match argument list for %s",
1737 m.lastf->type->toChars(),
1738 m.nextf->type->toChars(),
1739 m.lastf->toChars());
1740 #endif
1741 return m.lastf;
1746 /*************************************
1747 * Determine partial specialization order of 'this' vs g.
1748 * This is very similar to TemplateDeclaration::leastAsSpecialized().
1749 * Returns:
1750 * match 'this' is at least as specialized as g
1751 * 0 g is more specialized than 'this'
1754 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
1756 #define LOG_LEASTAS 0
1758 #if LOG_LEASTAS
1759 printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
1760 #endif
1762 /* This works by calling g() with f()'s parameters, and
1763 * if that is possible, then f() is at least as specialized
1764 * as g() is.
1767 TypeFunction *tf = (TypeFunction *)type;
1768 TypeFunction *tg = (TypeFunction *)g->type;
1769 size_t nfparams = Argument::dim(tf->parameters);
1770 size_t ngparams = Argument::dim(tg->parameters);
1771 MATCH match = MATCHexact;
1773 /* If both functions have a 'this' pointer, and the mods are not
1774 * the same and g's is not const, then this is less specialized.
1776 if (needThis() && g->needThis())
1778 if (tf->mod != tg->mod)
1780 if (tg->mod == MODconst)
1781 match = MATCHconst;
1782 else
1783 return MATCHnomatch;
1787 /* Create a dummy array of arguments out of the parameters to f()
1789 Expressions args;
1790 args.setDim(nfparams);
1791 for (int u = 0; u < nfparams; u++)
1793 Argument *p = Argument::getNth(tf->parameters, u);
1794 Expression *e = p->type->defaultInit();
1795 args.data[u] = e;
1798 MATCH m = (MATCH) tg->callMatch(NULL, &args);
1799 if (m)
1801 /* A variadic template is less specialized than a
1802 * non-variadic one.
1804 if (tf->varargs && !tg->varargs)
1805 goto L1; // less specialized
1807 #if LOG_LEASTAS
1808 printf(" matches %d, so is least as specialized\n", m);
1809 #endif
1810 return m;
1813 #if LOG_LEASTAS
1814 printf(" doesn't match, so is not as specialized\n");
1815 #endif
1816 return MATCHnomatch;
1819 /********************************
1820 * Labels are in a separate scope, one per function.
1823 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
1824 { Dsymbol *s;
1826 if (!labtab)
1827 labtab = new DsymbolTable(); // guess we need one
1829 s = labtab->lookup(ident);
1830 if (!s)
1832 s = new LabelDsymbol(ident);
1833 labtab->insert(s);
1835 return (LabelDsymbol *)s;
1838 /****************************************
1839 * If non-static member function that has a 'this' pointer,
1840 * return the aggregate it is a member of.
1841 * Otherwise, return NULL.
1844 AggregateDeclaration *FuncDeclaration::isThis()
1845 { AggregateDeclaration *ad;
1847 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1848 ad = NULL;
1849 if ((storage_class & STCstatic) == 0)
1851 ad = isMember2();
1853 //printf("-FuncDeclaration::isThis() %p\n", ad);
1854 return ad;
1857 AggregateDeclaration *FuncDeclaration::isMember2()
1858 { AggregateDeclaration *ad;
1860 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1861 ad = NULL;
1862 for (Dsymbol *s = this; s; s = s->parent)
1864 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1865 ad = s->isMember();
1866 if (ad)
1867 { //printf("test4\n");
1868 break;
1870 if (!s->parent ||
1871 (!s->parent->isTemplateInstance()))
1872 { //printf("test5\n");
1873 break;
1876 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1877 return ad;
1880 /*****************************************
1881 * Determine lexical level difference from 'this' to nested function 'fd'.
1882 * Error if this cannot call fd.
1883 * Returns:
1884 * 0 same level
1885 * -1 increase nesting by 1 (fd is nested within 'this')
1886 * >0 decrease nesting by number
1889 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
1890 { int level;
1891 Dsymbol *s;
1892 Dsymbol *fdparent;
1894 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1895 fdparent = fd->toParent2();
1896 if (fdparent == this)
1897 return -1;
1898 s = this;
1899 level = 0;
1900 while (fd != s && fdparent != s->toParent2())
1902 //printf("\ts = '%s'\n", s->toChars());
1903 FuncDeclaration *thisfd = s->isFuncDeclaration();
1904 if (thisfd)
1905 { if (!thisfd->isNested() && !thisfd->vthis)
1906 goto Lerr;
1908 else
1910 ClassDeclaration *thiscd = s->isClassDeclaration();
1911 if (thiscd)
1912 { if (!thiscd->isNested())
1913 goto Lerr;
1915 else
1916 goto Lerr;
1919 s = s->toParent2();
1920 assert(s);
1921 level++;
1923 return level;
1925 Lerr:
1926 error(loc, "cannot access frame of function %s", fd->toChars());
1927 return 1;
1930 void FuncDeclaration::appendExp(Expression *e)
1931 { Statement *s;
1933 s = new ExpStatement(0, e);
1934 appendState(s);
1937 void FuncDeclaration::appendState(Statement *s)
1938 { CompoundStatement *cs;
1940 if (!fbody)
1941 { Statements *a;
1943 a = new Statements();
1944 fbody = new CompoundStatement(0, a);
1946 cs = fbody->isCompoundStatement();
1947 cs->statements->push(s);
1951 int FuncDeclaration::isMain()
1953 return ident == Id::main &&
1954 linkage != LINKc && !isMember() && !isNested();
1957 int FuncDeclaration::isWinMain()
1959 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
1960 #if 0
1961 int x = ident == Id::WinMain &&
1962 linkage != LINKc && !isMember();
1963 printf("%s\n", x ? "yes" : "no");
1964 return x;
1965 #else
1966 return ident == Id::WinMain &&
1967 linkage != LINKc && !isMember();
1968 #endif
1971 int FuncDeclaration::isDllMain()
1973 return ident == Id::DllMain &&
1974 linkage != LINKc && !isMember();
1977 int FuncDeclaration::isExport()
1979 return protection == PROTexport;
1982 int FuncDeclaration::isImportedSymbol()
1984 //printf("isImportedSymbol()\n");
1985 //printf("protection = %d\n", protection);
1986 return (protection == PROTexport) && !fbody;
1989 // Determine if function goes into virtual function pointer table
1991 int FuncDeclaration::isVirtual()
1993 #if 0
1994 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1995 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
1996 printf("result is %d\n",
1997 isMember() &&
1998 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
1999 toParent()->isClassDeclaration());
2000 #endif
2001 return isMember() &&
2002 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2003 toParent()->isClassDeclaration();
2006 int FuncDeclaration::isFinal()
2008 #if 0
2009 printf("FuncDeclaration::isFinal(%s)\n", toChars());
2010 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2011 printf("result is %d\n",
2012 isMember() &&
2013 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2014 toParent()->isClassDeclaration());
2015 #endif
2016 ClassDeclaration *cd;
2017 return isMember() &&
2018 (Declaration::isFinal() ||
2019 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2022 int FuncDeclaration::isAbstract()
2024 return storage_class & STCabstract;
2027 int FuncDeclaration::isCodeseg()
2029 return TRUE; // functions are always in the code segment
2032 int FuncDeclaration::isOverloadable()
2034 return 1; // functions can be overloaded
2037 // Determine if function needs
2038 // a static frame pointer to its lexically enclosing function
2040 int FuncDeclaration::isNested()
2042 //if (!toParent())
2043 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2044 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2045 return ((storage_class & STCstatic) == 0) &&
2046 (toParent2()->isFuncDeclaration() != NULL);
2049 int FuncDeclaration::needThis()
2051 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2052 int i = isThis() != NULL;
2053 //printf("\t%d\n", i);
2054 if (!i && isFuncAliasDeclaration())
2055 i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
2056 return i;
2059 int FuncDeclaration::addPreInvariant()
2061 AggregateDeclaration *ad = isThis();
2062 return (ad &&
2063 //ad->isClassDeclaration() &&
2064 global.params.useInvariants &&
2065 (protection == PROTpublic || protection == PROTexport) &&
2066 !naked &&
2067 ident != Id::cpctor);
2070 int FuncDeclaration::addPostInvariant()
2072 AggregateDeclaration *ad = isThis();
2073 return (ad &&
2074 ad->inv &&
2075 //ad->isClassDeclaration() &&
2076 global.params.useInvariants &&
2077 (protection == PROTpublic || protection == PROTexport) &&
2078 !naked &&
2079 ident != Id::cpctor);
2082 /**********************************
2083 * Generate a FuncDeclaration for a runtime library function.
2086 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name,
2087 Type *t1, Type *t2, Type *t3)
2089 return genCfunc(treturn, Lexer::idPool(name), t1, t2, t3);
2092 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id,
2093 Type *t1, Type *t2, Type *t3)
2095 FuncDeclaration *fd;
2096 TypeFunction *tf;
2097 Dsymbol *s;
2098 static DsymbolTable *st = NULL;
2100 //printf("genCfunc(name = '%s')\n", id->toChars());
2101 //printf("treturn\n\t"); treturn->print();
2103 // See if already in table
2104 if (!st)
2105 st = new DsymbolTable();
2106 s = st->lookup(id);
2107 if (s)
2109 fd = s->isFuncDeclaration();
2110 assert(fd);
2111 assert(fd->type->nextOf()->equals(treturn));
2113 else
2115 Arguments * args = 0;
2116 if (t1) {
2117 args = new Arguments;
2118 args->push(new Argument(STCin,t1,0,0));
2119 if (t2)
2121 args->push(new Argument(STCin,t2,0,0));
2122 if (t3)
2123 args->push(new Argument(STCin,t3,0,0));
2127 tf = new TypeFunction(args, treturn, 0, LINKc);
2128 fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2129 fd->protection = PROTpublic;
2130 fd->linkage = LINKc;
2132 st->insert(fd);
2134 return fd;
2137 char *FuncDeclaration::kind()
2139 return "function";
2142 /*******************************
2143 * Look at all the variables in this function that are referenced
2144 * by nested functions, and determine if a closure needs to be
2145 * created for them.
2148 #if V2
2149 int FuncDeclaration::needsClosure()
2151 /* Need a closure for all the closureVars[] if any of the
2152 * closureVars[] are accessed by a
2153 * function that escapes the scope of this function.
2154 * We take the conservative approach and decide that any function that:
2155 * 1) is a virtual function
2156 * 2) has its address taken
2157 * 3) has a parent that escapes
2159 * Note that since a non-virtual function can be called by
2160 * a virtual one, if that non-virtual function accesses a closure
2161 * var, the closure still has to be taken. Hence, we check for isThis()
2162 * instead of isVirtual(). (thanks to David Friedman)
2165 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2166 for (int i = 0; i < closureVars.dim; i++)
2167 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
2168 assert(v->isVarDeclaration());
2169 //printf("\tv = %s\n", v->toChars());
2171 for (int j = 0; j < v->nestedrefs.dim; j++)
2172 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
2173 assert(f != this);
2175 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2176 if (f->isThis() || f->tookAddressOf)
2177 goto Lyes; // assume f escapes this function's scope
2179 // Look to see if any parents of f that are below this escape
2180 for (Dsymbol *s = f->parent; s != this; s = s->parent)
2182 f = s->isFuncDeclaration();
2183 if (f && (f->isThis() || f->tookAddressOf))
2184 goto Lyes;
2188 return 0;
2190 Lyes:
2191 //printf("\tneeds closure\n");
2192 return 1;
2194 #endif
2196 /****************************** FuncAliasDeclaration ************************/
2198 // Used as a way to import a set of functions from another scope into this one.
2200 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2201 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2202 (enum STC)funcalias->storage_class, funcalias->type)
2204 assert(funcalias != this);
2205 this->funcalias = funcalias;
2208 char *FuncAliasDeclaration::kind()
2210 return "function alias";
2214 /****************************** FuncLiteralDeclaration ************************/
2216 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2217 enum TOK tok, ForeachStatement *fes)
2218 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2220 char *id;
2222 if (fes)
2223 id = "__foreachbody";
2224 else if (tok == TOKdelegate)
2225 id = "__dgliteral";
2226 else
2227 id = "__funcliteral";
2228 this->ident = Identifier::generateId(id);
2229 this->tok = tok;
2230 this->fes = fes;
2231 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2234 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2236 FuncLiteralDeclaration *f;
2238 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2239 if (s)
2240 f = (FuncLiteralDeclaration *)s;
2241 else
2242 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2243 FuncDeclaration::syntaxCopy(f);
2244 return f;
2247 int FuncLiteralDeclaration::isNested()
2249 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2250 return (tok == TOKdelegate);
2253 char *FuncLiteralDeclaration::kind()
2255 // GCC requires the (char*) casts
2256 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
2259 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2261 static Identifier *idfunc;
2262 static Identifier *iddel;
2264 if (!idfunc)
2265 idfunc = new Identifier("function", 0);
2266 if (!iddel)
2267 iddel = new Identifier("delegate", 0);
2269 type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
2270 bodyToCBuffer(buf, hgs);
2274 /********************************* CtorDeclaration ****************************/
2276 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2277 : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
2279 this->arguments = arguments;
2280 this->varargs = varargs;
2281 //printf("CtorDeclaration() %s\n", toChars());
2284 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2286 CtorDeclaration *f;
2288 f = new CtorDeclaration(loc, endloc, NULL, varargs);
2290 f->outId = outId;
2291 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2292 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
2293 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
2294 assert(!fthrows); // deprecated
2296 f->arguments = Argument::arraySyntaxCopy(arguments);
2297 return f;
2301 void CtorDeclaration::semantic(Scope *sc)
2303 ClassDeclaration *cd;
2304 Type *tret;
2306 //printf("CtorDeclaration::semantic()\n");
2307 if (type)
2308 return;
2310 sc = sc->push();
2311 sc->stc &= ~STCstatic; // not a static constructor
2313 parent = sc->parent;
2314 Dsymbol *parent = toParent();
2315 cd = parent->isClassDeclaration();
2316 if (!cd)
2318 error("constructors are only for class definitions");
2319 tret = Type::tvoid;
2321 else
2323 tret = cd->type; //->referenceTo();
2325 for (int i = 0; i < cd->fields.dim; i++)
2327 VarDeclaration *vd = (VarDeclaration *) cd->fields.data[i];
2328 if (vd->storage_class & STCinject)
2330 if (!arguments)
2331 arguments = new Arguments();
2332 Argument *a = new Argument(vd->storage_class, vd->type, vd->ident, 0);
2333 // BUG: We don't really want these arguments in scope...
2334 arguments->push(a);
2336 Statement *assign = new ExpStatement(loc, new AssignExp(loc,
2337 new DotIdExp(loc, new ThisExp(loc), a->ident),
2338 new IdentifierExp(loc, a->ident)));
2339 if (fbody)
2340 fbody = new CompoundStatement(loc, assign, fbody);
2341 else
2342 fbody = assign;
2347 type = new TypeFunction(arguments, tret, varargs, LINKd);
2349 sc->flags |= SCOPEctor;
2350 type = type->semantic(loc, sc);
2351 sc->flags &= ~SCOPEctor;
2353 // Append:
2354 // return this;
2355 // to the function body
2356 if (fbody)
2357 { Expression *e;
2358 Statement *s;
2360 e = new ThisExp(0);
2361 s = new ReturnStatement(0, e);
2362 fbody = new CompoundStatement(0, fbody, s);
2365 FuncDeclaration::semantic(sc);
2367 sc->pop();
2369 // See if it's the default constructor
2370 if (cd && varargs == 0 && Argument::dim(arguments) == 0)
2371 cd->defaultCtor = this;
2374 char *CtorDeclaration::kind()
2376 return "constructor";
2379 char *CtorDeclaration::toChars()
2381 return "this";
2384 int CtorDeclaration::isVirtual()
2386 return FALSE;
2389 int CtorDeclaration::addPreInvariant()
2391 return FALSE;
2394 int CtorDeclaration::addPostInvariant()
2396 return (vthis && global.params.useInvariants);
2400 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2402 buf->writestring("this");
2403 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2404 bodyToCBuffer(buf, hgs);
2407 /********************************* PostBlitDeclaration ****************************/
2409 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
2410 : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
2414 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
2415 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2419 Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
2421 assert(!s);
2422 PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
2423 return FuncDeclaration::syntaxCopy(dd);
2427 void PostBlitDeclaration::semantic(Scope *sc)
2429 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2430 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2431 parent = sc->parent;
2432 Dsymbol *parent = toParent();
2433 StructDeclaration *ad = parent->isStructDeclaration();
2434 if (!ad)
2436 error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2438 else if (ident == Id::_postblit)
2439 ad->postblits.push(this);
2440 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2442 sc = sc->push();
2443 sc->stc &= ~STCstatic; // not static
2444 sc->linkage = LINKd;
2446 FuncDeclaration::semantic(sc);
2448 sc->pop();
2451 int PostBlitDeclaration::overloadInsert(Dsymbol *s)
2453 return FALSE; // cannot overload postblits
2456 int PostBlitDeclaration::addPreInvariant()
2458 return FALSE;
2461 int PostBlitDeclaration::addPostInvariant()
2463 return (vthis && global.params.useInvariants);
2466 int PostBlitDeclaration::isVirtual()
2468 return FALSE;
2471 void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2473 if (hgs->hdrgen)
2474 return;
2475 buf->writestring("=this()");
2476 bodyToCBuffer(buf, hgs);
2479 /********************************* DtorDeclaration ****************************/
2481 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
2482 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
2486 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
2487 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2491 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
2493 assert(!s);
2494 DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
2495 return FuncDeclaration::syntaxCopy(dd);
2499 void DtorDeclaration::semantic(Scope *sc)
2501 //printf("DtorDeclaration::semantic() %s\n", toChars());
2502 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2503 parent = sc->parent;
2504 Dsymbol *parent = toParent();
2505 AggregateDeclaration *ad = parent->isAggregateDeclaration();
2506 if (!ad)
2508 error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2510 else if (ident == Id::dtor)
2511 ad->dtors.push(this);
2512 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2514 sc = sc->push();
2515 sc->stc &= ~STCstatic; // not a static destructor
2516 sc->linkage = LINKd;
2518 FuncDeclaration::semantic(sc);
2520 sc->pop();
2523 int DtorDeclaration::overloadInsert(Dsymbol *s)
2525 return FALSE; // cannot overload destructors
2528 int DtorDeclaration::addPreInvariant()
2530 return (vthis && global.params.useInvariants);
2533 int DtorDeclaration::addPostInvariant()
2535 return FALSE;
2538 int DtorDeclaration::isVirtual()
2540 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2541 * but doing so will require recompiling everything.
2543 #if BREAKABI
2544 return FALSE;
2545 #else
2546 return FuncDeclaration::isVirtual();
2547 #endif
2550 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2552 if (hgs->hdrgen)
2553 return;
2554 buf->writestring("~this()");
2555 bodyToCBuffer(buf, hgs);
2558 /********************************* StaticCtorDeclaration ****************************/
2560 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
2561 : FuncDeclaration(loc, endloc,
2562 Identifier::generateId("_staticCtor"), STCstatic, NULL)
2566 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
2568 StaticCtorDeclaration *scd;
2570 assert(!s);
2571 scd = new StaticCtorDeclaration(loc, endloc);
2572 return FuncDeclaration::syntaxCopy(scd);
2576 void StaticCtorDeclaration::semantic(Scope *sc)
2578 //printf("StaticCtorDeclaration::semantic()\n");
2580 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2582 FuncDeclaration::semantic(sc);
2584 // We're going to need ModuleInfo
2585 Module *m = getModule();
2586 if (!m)
2587 m = sc->module;
2588 if (m)
2589 { m->needmoduleinfo = 1;
2590 #ifdef IN_GCC
2591 m->strictlyneedmoduleinfo = 1;
2592 #endif
2596 AggregateDeclaration *StaticCtorDeclaration::isThis()
2598 return NULL;
2601 int StaticCtorDeclaration::isStaticConstructor()
2603 return TRUE;
2606 int StaticCtorDeclaration::isVirtual()
2608 return FALSE;
2611 int StaticCtorDeclaration::addPreInvariant()
2613 return FALSE;
2616 int StaticCtorDeclaration::addPostInvariant()
2618 return FALSE;
2621 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2623 if (hgs->hdrgen)
2624 { buf->writestring("static this();\n");
2625 return;
2627 buf->writestring("static this()");
2628 bodyToCBuffer(buf, hgs);
2631 /********************************* StaticDtorDeclaration ****************************/
2633 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
2634 : FuncDeclaration(loc, endloc,
2635 Identifier::generateId("_staticDtor"), STCstatic, NULL)
2639 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
2641 StaticDtorDeclaration *sdd;
2643 assert(!s);
2644 sdd = new StaticDtorDeclaration(loc, endloc);
2645 return FuncDeclaration::syntaxCopy(sdd);
2649 void StaticDtorDeclaration::semantic(Scope *sc)
2651 ClassDeclaration *cd;
2652 Type *tret;
2654 cd = sc->scopesym->isClassDeclaration();
2655 if (!cd)
2658 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2660 FuncDeclaration::semantic(sc);
2662 // We're going to need ModuleInfo
2663 Module *m = getModule();
2664 if (!m)
2665 m = sc->module;
2666 if (m)
2667 { m->needmoduleinfo = 1;
2668 #ifdef IN_GCC
2669 m->strictlyneedmoduleinfo = 1;
2670 #endif
2674 AggregateDeclaration *StaticDtorDeclaration::isThis()
2676 return NULL;
2679 int StaticDtorDeclaration::isStaticDestructor()
2681 return TRUE;
2684 int StaticDtorDeclaration::isVirtual()
2686 return FALSE;
2689 int StaticDtorDeclaration::addPreInvariant()
2691 return FALSE;
2694 int StaticDtorDeclaration::addPostInvariant()
2696 return FALSE;
2699 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2701 if (hgs->hdrgen)
2702 return;
2703 buf->writestring("static ~this()");
2704 bodyToCBuffer(buf, hgs);
2707 /********************************* InvariantDeclaration ****************************/
2709 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
2710 : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
2714 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
2716 InvariantDeclaration *id;
2718 assert(!s);
2719 id = new InvariantDeclaration(loc, endloc);
2720 FuncDeclaration::syntaxCopy(id);
2721 return id;
2725 void InvariantDeclaration::semantic(Scope *sc)
2727 AggregateDeclaration *ad;
2728 Type *tret;
2730 parent = sc->parent;
2731 Dsymbol *parent = toParent();
2732 ad = parent->isAggregateDeclaration();
2733 if (!ad)
2735 error("invariants only are for struct/union/class definitions");
2736 return;
2738 else if (ad->inv && ad->inv != this)
2740 error("more than one invariant for %s", ad->toChars());
2742 ad->inv = this;
2743 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2745 sc = sc->push();
2746 sc->stc &= ~STCstatic; // not a static invariant
2747 sc->incontract++;
2748 sc->linkage = LINKd;
2750 FuncDeclaration::semantic(sc);
2752 sc->pop();
2755 int InvariantDeclaration::isVirtual()
2757 return FALSE;
2760 int InvariantDeclaration::addPreInvariant()
2762 return FALSE;
2765 int InvariantDeclaration::addPostInvariant()
2767 return FALSE;
2770 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2772 if (hgs->hdrgen)
2773 return;
2774 buf->writestring("invariant");
2775 bodyToCBuffer(buf, hgs);
2779 /********************************* UnitTestDeclaration ****************************/
2781 /*******************************
2782 * Generate unique unittest function Id so we can have multiple
2783 * instances per module.
2786 static Identifier *unitTestId()
2788 return Lexer::uniqueId("__unittest");
2791 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
2792 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
2796 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
2798 UnitTestDeclaration *utd;
2800 assert(!s);
2801 utd = new UnitTestDeclaration(loc, endloc);
2802 return FuncDeclaration::syntaxCopy(utd);
2806 void UnitTestDeclaration::semantic(Scope *sc)
2808 if (global.params.useUnitTests)
2810 Type *tret;
2812 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2813 FuncDeclaration::semantic(sc);
2816 // We're going to need ModuleInfo even if the unit tests are not
2817 // compiled in, because other modules may import this module and refer
2818 // to this ModuleInfo.
2819 Module *m = getModule();
2820 if (!m)
2821 m = sc->module;
2822 if (m)
2823 m->needmoduleinfo = 1;
2826 AggregateDeclaration *UnitTestDeclaration::isThis()
2828 return NULL;
2831 int UnitTestDeclaration::isVirtual()
2833 return FALSE;
2836 int UnitTestDeclaration::addPreInvariant()
2838 return FALSE;
2841 int UnitTestDeclaration::addPostInvariant()
2843 return FALSE;
2846 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2848 if (hgs->hdrgen)
2849 return;
2850 buf->writestring("unittest");
2851 bodyToCBuffer(buf, hgs);
2854 /********************************* NewDeclaration ****************************/
2856 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2857 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
2859 this->arguments = arguments;
2860 this->varargs = varargs;
2863 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
2865 NewDeclaration *f;
2867 f = new NewDeclaration(loc, endloc, NULL, varargs);
2869 FuncDeclaration::syntaxCopy(f);
2871 f->arguments = Argument::arraySyntaxCopy(arguments);
2873 return f;
2877 void NewDeclaration::semantic(Scope *sc)
2879 ClassDeclaration *cd;
2880 Type *tret;
2882 //printf("NewDeclaration::semantic()\n");
2884 parent = sc->parent;
2885 Dsymbol *parent = toParent();
2886 cd = parent->isClassDeclaration();
2887 if (!cd && !parent->isStructDeclaration())
2889 error("new allocators only are for class or struct definitions");
2891 tret = Type::tvoid->pointerTo();
2892 type = new TypeFunction(arguments, tret, varargs, LINKd);
2894 type = type->semantic(loc, sc);
2895 assert(type->ty == Tfunction);
2897 // Check that there is at least one argument of type uint
2898 TypeFunction *tf = (TypeFunction *)type;
2899 if (Argument::dim(tf->parameters) < 1)
2901 error("at least one argument of type uint expected");
2903 else
2905 Argument *a = Argument::getNth(tf->parameters, 0);
2906 if (!a->type->equals(Type::tuns32) &&
2907 (! global.params.isX86_64 || !a->type->equals(Type::tuns64)))
2908 error("first argument must be type uint, not %s", a->type->toChars());
2911 FuncDeclaration::semantic(sc);
2914 char *NewDeclaration::kind()
2916 return "allocator";
2919 int NewDeclaration::isVirtual()
2921 return FALSE;
2924 int NewDeclaration::addPreInvariant()
2926 return FALSE;
2929 int NewDeclaration::addPostInvariant()
2931 return FALSE;
2934 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2936 buf->writestring("new");
2937 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2938 bodyToCBuffer(buf, hgs);
2942 /********************************* DeleteDeclaration ****************************/
2944 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
2945 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
2947 this->arguments = arguments;
2950 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
2952 DeleteDeclaration *f;
2954 f = new DeleteDeclaration(loc, endloc, NULL);
2956 FuncDeclaration::syntaxCopy(f);
2958 f->arguments = Argument::arraySyntaxCopy(arguments);
2960 return f;
2964 void DeleteDeclaration::semantic(Scope *sc)
2966 ClassDeclaration *cd;
2968 //printf("DeleteDeclaration::semantic()\n");
2970 parent = sc->parent;
2971 Dsymbol *parent = toParent();
2972 cd = parent->isClassDeclaration();
2973 if (!cd && !parent->isStructDeclaration())
2975 error("new allocators only are for class or struct definitions");
2977 type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
2979 type = type->semantic(loc, sc);
2980 assert(type->ty == Tfunction);
2982 // Check that there is only one argument of type void*
2983 TypeFunction *tf = (TypeFunction *)type;
2984 if (Argument::dim(tf->parameters) != 1)
2986 error("one argument of type void* expected");
2988 else
2990 Argument *a = Argument::getNth(tf->parameters, 0);
2991 if (!a->type->equals(Type::tvoid->pointerTo()))
2992 error("one argument of type void* expected, not %s", a->type->toChars());
2995 FuncDeclaration::semantic(sc);
2998 char *DeleteDeclaration::kind()
3000 return "deallocator";
3003 int DeleteDeclaration::isDelete()
3005 return TRUE;
3008 int DeleteDeclaration::isVirtual()
3010 return FALSE;
3013 int DeleteDeclaration::addPreInvariant()
3015 return FALSE;
3018 int DeleteDeclaration::addPostInvariant()
3020 return FALSE;
3023 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3025 buf->writestring("delete");
3026 Argument::argsToCBuffer(buf, hgs, arguments, 0);
3027 bodyToCBuffer(buf, hgs);