comparison dmd2/func.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 356e65836fb5
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2008 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <assert.h>
12
13 #include "mars.h"
14 #include "init.h"
15 #include "declaration.h"
16 #include "attrib.h"
17 #include "expression.h"
18 #include "scope.h"
19 #include "mtype.h"
20 #include "aggregate.h"
21 #include "identifier.h"
22 #include "id.h"
23 #include "module.h"
24 #include "statement.h"
25 #include "template.h"
26 #include "hdrgen.h"
27
28 #ifdef IN_GCC
29 #include "d-dmd-gcc.h"
30 #endif
31
32 /********************************* FuncDeclaration ****************************/
33
34 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
35 : Declaration(id)
36 {
37 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
38 this->storage_class = storage_class;
39 this->type = type;
40 this->loc = loc;
41 this->endloc = endloc;
42 fthrows = NULL;
43 frequire = NULL;
44 outId = NULL;
45 vresult = NULL;
46 returnLabel = NULL;
47 fensure = NULL;
48 fbody = NULL;
49 localsymtab = NULL;
50 vthis = NULL;
51 v_arguments = NULL;
52 #if IN_GCC
53 v_argptr = NULL;
54 #endif
55 parameters = NULL;
56 labtab = NULL;
57 overnext = NULL;
58 vtblIndex = -1;
59 hasReturnExp = 0;
60 naked = 0;
61 inlineStatus = ILSuninitialized;
62 inlineNest = 0;
63 inlineAsm = 0;
64 cantInterpret = 0;
65 semanticRun = 0;
66 fes = NULL;
67 introducing = 0;
68 tintro = NULL;
69 /* The type given for "infer the return type" is a TypeFunction with
70 * NULL for the return type.
71 */
72 inferRetType = (type && type->nextOf() == NULL);
73 scope = NULL;
74 hasReturnExp = 0;
75 nrvo_can = 1;
76 nrvo_var = NULL;
77 shidden = NULL;
78 builtin = BUILTINunknown;
79 tookAddressOf = 0;
80
81 // LDC
82 isArrayOp = false;
83 }
84
85 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
86 {
87 FuncDeclaration *f;
88
89 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
90 if (s)
91 f = (FuncDeclaration *)s;
92 else
93 f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
94 f->outId = outId;
95 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
96 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
97 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
98 assert(!fthrows); // deprecated
99
100 // LDC
101 f->intrinsicName = intrinsicName;
102
103 return f;
104 }
105
106
107 // Do the semantic analysis on the external interface to the function.
108
109 void FuncDeclaration::semantic(Scope *sc)
110 { TypeFunction *f;
111 StructDeclaration *sd;
112 ClassDeclaration *cd;
113 InterfaceDeclaration *id;
114 Dsymbol *pd;
115
116 #if 0
117 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
118 if (isFuncLiteralDeclaration())
119 printf("\tFuncLiteralDeclaration()\n");
120 printf("sc->parent = %s\n", sc->parent->toChars());
121 printf("type: %p, %s\n", type, type->toChars());
122 #endif
123
124 storage_class |= sc->stc & ~STCref;
125 //printf("function storage_class = x%x\n", storage_class);
126
127 if (!originalType)
128 originalType = type;
129 if (!type->deco && type->nextOf())
130 {
131 #if 1
132 /* Apply const and invariant storage class
133 * to the function type
134 */
135 type = type->semantic(loc, sc);
136 if (storage_class & STCinvariant)
137 { // Don't use toInvariant(), as that will do a merge()
138 type = type->makeInvariant();
139 type->deco = type->merge()->deco;
140 }
141 else if (storage_class & STCconst)
142 {
143 if (!type->isInvariant())
144 { // Don't use toConst(), as that will do a merge()
145 type = type->makeConst();
146 type->deco = type->merge()->deco;
147 }
148 }
149 #else
150 if (storage_class & (STCconst | STCinvariant))
151 {
152 /* Apply const and invariant storage class
153 * to the function's return type
154 */
155 Type *tn = type->nextOf();
156 if (storage_class & STCconst)
157 tn = tn->makeConst();
158 if (storage_class & STCinvariant)
159 tn = tn->makeInvariant();
160 ((TypeNext *)type)->next = tn;
161 }
162
163 type = type->semantic(loc, sc);
164 #endif
165 }
166 //type->print();
167 if (type->ty != Tfunction)
168 {
169 error("%s must be a function", toChars());
170 return;
171 }
172 f = (TypeFunction *)(type);
173
174 size_t nparams = Argument::dim(f->parameters);
175
176 linkage = sc->linkage;
177 // if (!parent)
178 {
179 //parent = sc->scopesym;
180 parent = sc->parent;
181 }
182 protection = sc->protection;
183 Dsymbol *parent = toParent();
184
185 if (storage_class & STCscope)
186 error("functions cannot be scope");
187
188 if (isAbstract() && !isVirtual())
189 error("non-virtual functions cannot be abstract");
190
191 if ((f->isConst() || f->isInvariant()) && !isThis())
192 error("without 'this' cannot be const/invariant");
193
194 if (isAbstract() && isFinal())
195 error("cannot be both final and abstract");
196 #if 0
197 if (isAbstract() && fbody)
198 error("abstract functions cannot have bodies");
199 #endif
200
201 #if 0
202 if (isStaticConstructor() || isStaticDestructor())
203 {
204 if (!isStatic() || type->nextOf()->ty != Tvoid)
205 error("static constructors / destructors must be static void");
206 if (f->arguments && f->arguments->dim)
207 error("static constructors / destructors must have empty parameter list");
208 // BUG: check for invalid storage classes
209 }
210 #endif
211
212 #ifdef IN_GCC
213 AggregateDeclaration *ad;
214
215 ad = parent->isAggregateDeclaration();
216 if (ad)
217 ad->methods.push(this);
218 #endif
219 sd = parent->isStructDeclaration();
220 if (sd)
221 {
222 if (isCtorDeclaration())
223 {
224 return;
225 }
226 #if 0
227 // Verify no constructors, destructors, etc.
228 if (isCtorDeclaration()
229 //||isDtorDeclaration()
230 //|| isInvariantDeclaration()
231 //|| isUnitTestDeclaration()
232 )
233 {
234 error("special member functions not allowed for %ss", sd->kind());
235 }
236
237 if (!sd->inv)
238 sd->inv = isInvariantDeclaration();
239
240 if (!sd->aggNew)
241 sd->aggNew = isNewDeclaration();
242
243 if (isDelete())
244 {
245 if (sd->aggDelete)
246 error("multiple delete's for struct %s", sd->toChars());
247 sd->aggDelete = (DeleteDeclaration *)(this);
248 }
249 #endif
250 }
251
252 id = parent->isInterfaceDeclaration();
253 if (id)
254 {
255 storage_class |= STCabstract;
256
257 if (isCtorDeclaration() ||
258 isPostBlitDeclaration() ||
259 isDtorDeclaration() ||
260 isInvariantDeclaration() ||
261 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
262 error("special function not allowed in interface %s", id->toChars());
263 if (fbody)
264 error("function body is not abstract in interface %s", id->toChars());
265 }
266
267 /* Template member functions aren't virtual:
268 * interface TestInterface { void tpl(T)(); }
269 * and so won't work in interfaces
270 */
271 if ((pd = toParent()) != NULL &&
272 pd->isTemplateInstance() &&
273 (pd = toParent2()) != NULL &&
274 (id = pd->isInterfaceDeclaration()) != NULL)
275 {
276 error("template member function not allowed in interface %s", id->toChars());
277 }
278
279 cd = parent->isClassDeclaration();
280 if (cd)
281 { int vi;
282 CtorDeclaration *ctor;
283 DtorDeclaration *dtor;
284 InvariantDeclaration *inv;
285
286 if (isCtorDeclaration())
287 {
288 // ctor = (CtorDeclaration *)this;
289 // if (!cd->ctor)
290 // cd->ctor = ctor;
291 return;
292 }
293
294 #if 0
295 dtor = isDtorDeclaration();
296 if (dtor)
297 {
298 if (cd->dtor)
299 error("multiple destructors for class %s", cd->toChars());
300 cd->dtor = dtor;
301 }
302
303 inv = isInvariantDeclaration();
304 if (inv)
305 {
306 cd->inv = inv;
307 }
308
309 if (isNewDeclaration())
310 {
311 if (!cd->aggNew)
312 cd->aggNew = (NewDeclaration *)(this);
313 }
314
315 if (isDelete())
316 {
317 if (cd->aggDelete)
318 error("multiple delete's for class %s", cd->toChars());
319 cd->aggDelete = (DeleteDeclaration *)(this);
320 }
321 #endif
322
323 if (storage_class & STCabstract)
324 cd->isabstract = 1;
325
326 // if static function, do not put in vtbl[]
327 if (!isVirtual())
328 {
329 //printf("\tnot virtual\n");
330 goto Ldone;
331 }
332
333 // Find index of existing function in vtbl[] to override
334 vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
335 switch (vi)
336 {
337 case -1:
338 /* Didn't find one, so
339 * This is an 'introducing' function which gets a new
340 * slot in the vtbl[].
341 */
342
343 // Verify this doesn't override previous final function
344 if (cd->baseClass)
345 { Dsymbol *s = cd->baseClass->search(loc, ident, 0);
346 if (s)
347 {
348 FuncDeclaration *f = s->isFuncDeclaration();
349 f = f->overloadExactMatch(type);
350 if (f && f->isFinal() && f->prot() != PROTprivate)
351 error("cannot override final function %s", f->toPrettyChars());
352 }
353 }
354
355 if (isFinal())
356 {
357 cd->vtblFinal.push(this);
358 }
359 else
360 {
361 // Append to end of vtbl[]
362 //printf("\tintroducing function\n");
363 introducing = 1;
364 vi = cd->vtbl.dim;
365 cd->vtbl.push(this);
366 vtblIndex = vi;
367 }
368 break;
369
370 case -2: // can't determine because of fwd refs
371 cd->sizeok = 2; // can't finish due to forward reference
372 return;
373
374 default:
375 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
376 // This function is covariant with fdv
377 if (fdv->isFinal())
378 error("cannot override final function %s", fdv->toPrettyChars());
379
380 #if DMDV2
381 if (!isOverride() && global.params.warnings)
382 warning("%s: overrides base class function %s, but is not marked with 'override'", locToChars(), fdv->toPrettyChars());
383 #endif
384
385 if (fdv->toParent() == parent)
386 {
387 // If both are mixins, then error.
388 // If either is not, the one that is not overrides
389 // the other.
390 if (fdv->parent->isClassDeclaration())
391 break;
392 if (!this->parent->isClassDeclaration()
393 #if !BREAKABI
394 && !isDtorDeclaration()
395 #endif
396 #if DMDV2
397 && !isPostBlitDeclaration()
398 #endif
399 )
400 error("multiple overrides of same function");
401 }
402 cd->vtbl.data[vi] = (void *)this;
403 vtblIndex = vi;
404
405 /* This works by whenever this function is called,
406 * it actually returns tintro, which gets dynamically
407 * cast to type. But we know that tintro is a base
408 * of type, so we could optimize it by not doing a
409 * dynamic cast, but just subtracting the isBaseOf()
410 * offset if the value is != null.
411 */
412
413 if (fdv->tintro)
414 tintro = fdv->tintro;
415 else if (!type->equals(fdv->type))
416 {
417 /* Only need to have a tintro if the vptr
418 * offsets differ
419 */
420 int offset;
421 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
422 {
423 tintro = fdv->type;
424 }
425 }
426 break;
427 }
428 }
429
430 /* Go through all the interface bases.
431 * If this function is covariant with any members of those interface
432 * functions, set the tintro.
433 */
434 for (int i = 0; i < cd->interfaces_dim; i++)
435 {
436 BaseClass *b = cd->interfaces[i];
437 vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
438 switch (vi)
439 {
440 case -1:
441 break;
442
443 case -2:
444 cd->sizeok = 2; // can't finish due to forward reference
445 return;
446
447 default:
448 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
449 Type *ti = NULL;
450
451 if (fdv->tintro)
452 ti = fdv->tintro;
453 else if (!type->equals(fdv->type))
454 {
455 /* Only need to have a tintro if the vptr
456 * offsets differ
457 */
458 int offset;
459 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
460 {
461 ti = fdv->type;
462 #if 0
463 if (offset)
464 ti = fdv->type;
465 else if (type->nextOf()->ty == Tclass)
466 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
467 if (cdn && cdn->sizeok != 1)
468 ti = fdv->type;
469 }
470 #endif
471 }
472 }
473 if (ti)
474 {
475 if (tintro && !tintro->equals(ti))
476 {
477 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
478 }
479 tintro = ti;
480 }
481 goto L2;
482 }
483 }
484 }
485
486 if (introducing && isOverride())
487 {
488 error("does not override any function");
489 }
490
491 L2: ;
492 }
493 else if (isOverride() && !parent->isTemplateInstance())
494 error("override only applies to class member functions");
495
496 /* Do not allow template instances to add virtual functions
497 * to a class.
498 */
499 if (isVirtual())
500 {
501 TemplateInstance *ti = parent->isTemplateInstance();
502 if (ti)
503 {
504 // Take care of nested templates
505 while (1)
506 {
507 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
508 if (!ti2)
509 break;
510 ti = ti2;
511 }
512
513 // If it's a member template
514 ClassDeclaration *cd = ti->tempdecl->isClassMember();
515 if (cd)
516 {
517 error("cannot use template to add virtual function to class '%s'", cd->toChars());
518 }
519 }
520 }
521
522 if (isMain())
523 {
524 // Check parameters to see if they are either () or (char[][] args)
525 switch (nparams)
526 {
527 case 0:
528 break;
529
530 case 1:
531 {
532 Argument *arg0 = Argument::getNth(f->parameters, 0);
533 if (arg0->type->ty != Tarray ||
534 arg0->type->nextOf()->ty != Tarray ||
535 arg0->type->nextOf()->nextOf()->ty != Tchar ||
536 arg0->storageClass & (STCout | STCref | STClazy))
537 goto Lmainerr;
538 break;
539 }
540
541 default:
542 goto Lmainerr;
543 }
544
545 if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
546 error("must return int or void, not %s", f->nextOf()->toChars());
547 if (f->varargs)
548 {
549 Lmainerr:
550 error("parameters must be main() or main(char[][] args)");
551 }
552 }
553
554 if (ident == Id::assign && (sd || cd))
555 { // Disallow identity assignment operator.
556
557 // opAssign(...)
558 if (nparams == 0)
559 { if (f->varargs == 1)
560 goto Lassignerr;
561 }
562 else
563 {
564 Argument *arg0 = Argument::getNth(f->parameters, 0);
565 Type *t0 = arg0->type->toBasetype();
566 Type *tb = sd ? sd->type : cd->type;
567 if (arg0->type->implicitConvTo(tb) ||
568 (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
569 )
570 {
571 if (nparams == 1)
572 goto Lassignerr;
573 Argument *arg1 = Argument::getNth(f->parameters, 1);
574 if (arg1->defaultArg)
575 goto Lassignerr;
576 }
577 }
578 }
579
580 Ldone:
581 /* Save scope for possible later use (if we need the
582 * function internals)
583 */
584 scope = new Scope(*sc);
585 scope->setNoFree();
586 return;
587
588 Lassignerr:
589 if (sd)
590 {
591 sd->hasIdentityAssign = 1; // don't need to generate it
592 goto Ldone;
593 }
594 error("identity assignment operator overload is illegal");
595 }
596
597 void FuncDeclaration::semantic2(Scope *sc)
598 {
599 }
600
601 // Do the semantic analysis on the internals of the function.
602
603 void FuncDeclaration::semantic3(Scope *sc)
604 { TypeFunction *f;
605 AggregateDeclaration *ad;
606 VarDeclaration *argptr = NULL;
607 VarDeclaration *_arguments = NULL;
608
609 if (!parent)
610 {
611 if (global.errors)
612 return;
613 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
614 assert(0);
615 }
616 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
617 //fflush(stdout);
618 //{ static int x; if (++x == 2) *(char*)0=0; }
619 //printf("\tlinkage = %d\n", sc->linkage);
620
621 //printf(" sc->incontract = %d\n", sc->incontract);
622 if (semanticRun)
623 return;
624 semanticRun = 1;
625
626 if (!type || type->ty != Tfunction)
627 return;
628 f = (TypeFunction *)(type);
629
630 // Check the 'throws' clause
631 if (fthrows)
632 {
633 for (int i = 0; i < fthrows->dim; i++)
634 {
635 Type *t = (Type *)fthrows->data[i];
636
637 t = t->semantic(loc, sc);
638 if (!t->isClassHandle())
639 error("can only throw classes, not %s", t->toChars());
640 }
641 }
642
643 if (fbody || frequire)
644 {
645 /* Symbol table into which we place parameters and nested functions,
646 * solely to diagnose name collisions.
647 */
648 localsymtab = new DsymbolTable();
649
650 // Establish function scope
651 ScopeDsymbol *ss = new ScopeDsymbol();
652 ss->parent = sc->scopesym;
653 Scope *sc2 = sc->push(ss);
654 sc2->func = this;
655 sc2->parent = this;
656 sc2->callSuper = 0;
657 sc2->sbreak = NULL;
658 sc2->scontinue = NULL;
659 sc2->sw = NULL;
660 sc2->fes = fes;
661 sc2->linkage = LINKd;
662 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCconst | STCfinal | STCinvariant | STCtls);
663 sc2->protection = PROTpublic;
664 sc2->explicitProtection = 0;
665 sc2->structalign = 8;
666 sc2->incontract = 0;
667 sc2->tf = NULL;
668 sc2->tfOfTry = NULL;
669 sc2->noctor = 0;
670
671 // Declare 'this'
672 ad = isThis();
673 if (ad)
674 { VarDeclaration *v;
675
676 if (isFuncLiteralDeclaration() && isNested())
677 {
678 error("literals cannot be class members");
679 return;
680 }
681 else
682 {
683 assert(!isNested()); // can't be both member and nested
684 assert(ad->handle);
685 Type *thandle = ad->handle;
686 if (storage_class & STCconst || type->isConst())
687 {
688 if (thandle->ty == Tclass)
689 thandle = thandle->constOf();
690 else
691 { assert(thandle->ty == Tpointer);
692 thandle = thandle->nextOf()->constOf()->pointerTo();
693 }
694 }
695 else if (storage_class & STCinvariant || type->isInvariant())
696 {
697 if (thandle->ty == Tclass)
698 thandle = thandle->invariantOf();
699 else
700 { assert(thandle->ty == Tpointer);
701 thandle = thandle->nextOf()->invariantOf()->pointerTo();
702 }
703 }
704 v = new ThisDeclaration(thandle);
705 v->storage_class |= STCparameter;
706 v->semantic(sc2);
707 if (!sc2->insert(v))
708 assert(0);
709 v->parent = this;
710 vthis = v;
711 }
712 }
713 else if (isNested())
714 {
715 /* The 'this' for a nested function is the link to the
716 * enclosing function's stack frame.
717 * Note that nested functions and member functions are disjoint.
718 */
719 VarDeclaration *v = new ThisDeclaration(Type::tvoid->pointerTo());
720 v->storage_class |= STCparameter;
721 v->semantic(sc2);
722 if (!sc2->insert(v))
723 assert(0);
724 v->parent = this;
725 vthis = v;
726 }
727
728 // Declare hidden variable _arguments[] and _argptr
729 if (f->varargs == 1)
730 { Type *t;
731
732 if (f->linkage == LINKd)
733 { // Declare _arguments[]
734 #if BREAKABI
735 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
736 v_arguments->storage_class = STCparameter;
737 v_arguments->semantic(sc2);
738 sc2->insert(v_arguments);
739 v_arguments->parent = this;
740
741 //t = Type::typeinfo->type->constOf()->arrayOf();
742 t = Type::typeinfo->type->arrayOf();
743 _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
744 _arguments->semantic(sc2);
745 sc2->insert(_arguments);
746 _arguments->parent = this;
747 #else
748 t = Type::typeinfo->type->arrayOf();
749 v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
750 v_arguments->storage_class = STCparameter | STCin;
751 v_arguments->semantic(sc2);
752 sc2->insert(v_arguments);
753 v_arguments->parent = this;
754 #endif
755 }
756 if (f->linkage == LINKd || (parameters && parameters->dim))
757 { // Declare _argptr
758 #if IN_GCC
759 t = d_gcc_builtin_va_list_d_type;
760 #else
761 t = Type::tvoid->pointerTo();
762 #endif
763 argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
764 argptr->semantic(sc2);
765 sc2->insert(argptr);
766 argptr->parent = this;
767 }
768 }
769
770 // Propagate storage class from tuple parameters to their element-parameters.
771 if (f->parameters)
772 {
773 for (size_t i = 0; i < f->parameters->dim; i++)
774 { Argument *arg = (Argument *)f->parameters->data[i];
775
776 if (arg->type->ty == Ttuple)
777 { TypeTuple *t = (TypeTuple *)arg->type;
778 size_t dim = Argument::dim(t->arguments);
779 for (size_t j = 0; j < dim; j++)
780 { Argument *narg = Argument::getNth(t->arguments, j);
781 narg->storageClass = arg->storageClass;
782 }
783 }
784 }
785 }
786
787 /* Declare all the function parameters as variables
788 * and install them in parameters[]
789 */
790 size_t nparams = Argument::dim(f->parameters);
791 if (nparams)
792 { /* parameters[] has all the tuples removed, as the back end
793 * doesn't know about tuples
794 */
795 parameters = new Dsymbols();
796 parameters->reserve(nparams);
797 for (size_t i = 0; i < nparams; i++)
798 {
799 Argument *arg = Argument::getNth(f->parameters, i);
800 Identifier *id = arg->ident;
801 if (!id)
802 {
803 /* Generate identifier for un-named parameter,
804 * because we need it later on.
805 */
806 arg->ident = id = Identifier::generateId("_param_", i);
807 }
808 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
809 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
810 v->storage_class |= STCparameter;
811 if (f->varargs == 2 && i + 1 == nparams)
812 v->storage_class |= STCvariadic;
813 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STCconst | STCinvariant | STCnodtor);
814 v->semantic(sc2);
815 if (!sc2->insert(v))
816 error("parameter %s.%s is already defined", toChars(), v->toChars());
817 else
818 parameters->push(v);
819 localsymtab->insert(v);
820 v->parent = this;
821 }
822 }
823
824 // Declare the tuple symbols and put them in the symbol table,
825 // but not in parameters[].
826 if (f->parameters)
827 {
828 for (size_t i = 0; i < f->parameters->dim; i++)
829 { Argument *arg = (Argument *)f->parameters->data[i];
830
831 if (!arg->ident)
832 continue; // never used, so ignore
833 if (arg->type->ty == Ttuple)
834 { TypeTuple *t = (TypeTuple *)arg->type;
835 size_t dim = Argument::dim(t->arguments);
836 Objects *exps = new Objects();
837 exps->setDim(dim);
838 for (size_t j = 0; j < dim; j++)
839 { Argument *narg = Argument::getNth(t->arguments, j);
840 assert(narg->ident);
841 VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
842 assert(v);
843 Expression *e = new VarExp(v->loc, v);
844 exps->data[j] = (void *)e;
845 }
846 assert(arg->ident);
847 TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
848 //printf("declaring tuple %s\n", v->toChars());
849 v->isexp = 1;
850 if (!sc2->insert(v))
851 error("parameter %s.%s is already defined", toChars(), v->toChars());
852 localsymtab->insert(v);
853 v->parent = this;
854 }
855 }
856 }
857
858 /* Do the semantic analysis on the [in] preconditions and
859 * [out] postconditions.
860 */
861 sc2->incontract++;
862
863 if (frequire)
864 { /* frequire is composed of the [in] contracts
865 */
866 // BUG: need to error if accessing out parameters
867 // BUG: need to treat parameters as const
868 // BUG: need to disallow returns and throws
869 // BUG: verify that all in and ref parameters are read
870 frequire = frequire->semantic(sc2);
871 labtab = NULL; // so body can't refer to labels
872 }
873
874 if (fensure || addPostInvariant())
875 { /* fensure is composed of the [out] contracts
876 */
877 ScopeDsymbol *sym = new ScopeDsymbol();
878 sym->parent = sc2->scopesym;
879 sc2 = sc2->push(sym);
880
881 assert(type->nextOf());
882 if (type->nextOf()->ty == Tvoid)
883 {
884 if (outId)
885 error("void functions have no result");
886 }
887 else
888 {
889 if (!outId)
890 outId = Id::result; // provide a default
891 }
892
893 if (outId)
894 { // Declare result variable
895 VarDeclaration *v;
896 Loc loc = this->loc;
897
898 if (fensure)
899 loc = fensure->loc;
900
901 v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
902 v->noauto = 1;
903 sc2->incontract--;
904 v->semantic(sc2);
905 sc2->incontract++;
906 if (!sc2->insert(v))
907 error("out result %s is already defined", v->toChars());
908 v->parent = this;
909 vresult = v;
910
911 // vresult gets initialized with the function return value
912 // in ReturnStatement::semantic()
913 }
914
915 // BUG: need to treat parameters as const
916 // BUG: need to disallow returns and throws
917 if (fensure)
918 { fensure = fensure->semantic(sc2);
919 labtab = NULL; // so body can't refer to labels
920 }
921
922 if (!global.params.useOut)
923 { fensure = NULL; // discard
924 vresult = NULL;
925 }
926
927 // Postcondition invariant
928 if (addPostInvariant())
929 {
930 Expression *e = NULL;
931 if (isCtorDeclaration())
932 {
933 // Call invariant directly only if it exists
934 InvariantDeclaration *inv = ad->inv;
935 ClassDeclaration *cd = ad->isClassDeclaration();
936
937 while (!inv && cd)
938 {
939 cd = cd->baseClass;
940 if (!cd)
941 break;
942 inv = cd->inv;
943 }
944 if (inv)
945 {
946 e = new DsymbolExp(0, inv);
947 e = new CallExp(0, e);
948 e = e->semantic(sc2);
949 }
950 }
951 else
952 { // Call invariant virtually
953 ThisExp *v = new ThisExp(0);
954 v->type = vthis->type;
955 e = new AssertExp(0, v);
956 }
957 if (e)
958 {
959 ExpStatement *s = new ExpStatement(0, e);
960 if (fensure)
961 fensure = new CompoundStatement(0, s, fensure);
962 else
963 fensure = s;
964 }
965 }
966
967 if (fensure)
968 { returnLabel = new LabelDsymbol(Id::returnLabel);
969 LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
970 ls->isReturnLabel = 1;
971 returnLabel->statement = ls;
972 }
973 sc2 = sc2->pop();
974 }
975
976 sc2->incontract--;
977
978 if (fbody)
979 { ClassDeclaration *cd = isClassMember();
980
981 /* If this is a class constructor
982 */
983 if (isCtorDeclaration() && cd)
984 {
985 for (int i = 0; i < cd->fields.dim; i++)
986 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
987
988 v->ctorinit = 0;
989 }
990 }
991
992 if (inferRetType || f->retStyle() != RETstack)
993 nrvo_can = 0;
994
995 fbody = fbody->semantic(sc2);
996
997 if (inferRetType)
998 { // If no return type inferred yet, then infer a void
999 if (!type->nextOf())
1000 {
1001 ((TypeFunction *)type)->next = Type::tvoid;
1002 type = type->semantic(loc, sc);
1003 }
1004 f = (TypeFunction *)type;
1005 }
1006
1007 if (isStaticCtorDeclaration())
1008 { /* It's a static constructor. Ensure that all
1009 * ctor consts were initialized.
1010 */
1011
1012 Dsymbol *p = toParent();
1013 ScopeDsymbol *ad = p->isScopeDsymbol();
1014 if (!ad)
1015 {
1016 error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
1017 }
1018 else
1019 {
1020 for (int i = 0; i < ad->members->dim; i++)
1021 { Dsymbol *s = (Dsymbol *)ad->members->data[i];
1022
1023 s->checkCtorConstInit();
1024 }
1025 }
1026 }
1027
1028 if (isCtorDeclaration() && cd)
1029 {
1030 //printf("callSuper = x%x\n", sc2->callSuper);
1031
1032 // Verify that all the ctorinit fields got initialized
1033 if (!(sc2->callSuper & CSXthis_ctor))
1034 {
1035 for (int i = 0; i < cd->fields.dim; i++)
1036 { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
1037
1038 if (v->ctorinit == 0 && v->isCtorinit())
1039 error("missing initializer for final field %s", v->toChars());
1040 }
1041 }
1042
1043 if (!(sc2->callSuper & CSXany_ctor) &&
1044 cd->baseClass && cd->baseClass->ctor)
1045 {
1046 sc2->callSuper = 0;
1047
1048 // Insert implicit super() at start of fbody
1049 Expression *e1 = new SuperExp(0);
1050 Expression *e = new CallExp(0, e1);
1051
1052 unsigned errors = global.errors;
1053 global.gag++;
1054 e = e->semantic(sc2);
1055 global.gag--;
1056 if (errors != global.errors)
1057 error("no match for implicit super() call in constructor");
1058
1059 Statement *s = new ExpStatement(0, e);
1060 fbody = new CompoundStatement(0, s, fbody);
1061 }
1062 }
1063 else if (fes)
1064 { // For foreach(){} body, append a return 0;
1065 Expression *e = new IntegerExp(0);
1066 Statement *s = new ReturnStatement(0, e);
1067 fbody = new CompoundStatement(0, fbody, s);
1068 assert(!returnLabel);
1069 }
1070 else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1071 error("expected to return a value of type %s", type->nextOf()->toChars());
1072 else if (!inlineAsm)
1073 {
1074 int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
1075 //int offend = fbody ? fbody->fallOffEnd() : TRUE;
1076
1077 if (type->nextOf()->ty == Tvoid)
1078 {
1079 if (offend && isMain())
1080 { // Add a return 0; statement
1081 Statement *s = new ReturnStatement(0, new IntegerExp(0));
1082 fbody = new CompoundStatement(0, fbody, s);
1083 }
1084 }
1085 else
1086 {
1087 if (offend)
1088 { Expression *e;
1089
1090 if (global.params.warnings)
1091 { warning("%s: no return at end of function", locToChars());
1092 }
1093
1094 if (global.params.useAssert &&
1095 !global.params.useInline)
1096 { /* Add an assert(0, msg); where the missing return
1097 * should be.
1098 */
1099 e = new AssertExp(
1100 endloc,
1101 new IntegerExp(0),
1102 new StringExp(loc, (char *)"missing return expression")
1103 );
1104 }
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);
1111 }
1112 }
1113 }
1114 }
1115
1116 {
1117 Statements *a = new Statements();
1118
1119 // Merge in initialization of 'out' parameters
1120 if (parameters)
1121 { for (size_t i = 0; i < parameters->dim; i++)
1122 {
1123 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1124 if (v->storage_class & STCout)
1125 {
1126 assert(v->init);
1127 ExpInitializer *ie = v->init->isExpInitializer();
1128 assert(ie);
1129 a->push(new ExpStatement(0, ie->exp));
1130 }
1131 }
1132 }
1133
1134 // we'll handle variadics ourselves
1135 #if !IN_LLVM
1136 if (argptr)
1137 { // Initialize _argptr to point past non-variadic arg
1138 #if IN_GCC
1139 // Handled in FuncDeclaration::toObjFile
1140 v_argptr = argptr;
1141 v_argptr->init = new VoidInitializer(loc);
1142 #else
1143 Expression *e1;
1144 Expression *e;
1145 Type *t = argptr->type;
1146 VarDeclaration *p;
1147 unsigned offset;
1148
1149 e1 = new VarExp(0, argptr);
1150 if (parameters && parameters->dim)
1151 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1152 else
1153 p = v_arguments; // last parameter is _arguments[]
1154 offset = p->type->size();
1155 offset = (offset + 3) & ~3; // assume stack aligns on 4
1156 e = new SymOffExp(0, p, offset);
1157 e = new AssignExp(0, e1, e);
1158 e->type = t;
1159 a->push(new ExpStatement(0, e));
1160 #endif // IN_GCC
1161 }
1162
1163 if (_arguments)
1164 {
1165 /* Advance to elements[] member of TypeInfo_Tuple with:
1166 * _arguments = v_arguments.elements;
1167 */
1168 Expression *e = new VarExp(0, v_arguments);
1169 e = new DotIdExp(0, e, Id::elements);
1170 Expression *e1 = new VarExp(0, _arguments);
1171 e = new AssignExp(0, e1, e);
1172 e->op = TOKconstruct;
1173 e = e->semantic(sc);
1174 a->push(new ExpStatement(0, e));
1175 }
1176
1177 #endif // !IN_LLVM
1178
1179 // Merge contracts together with body into one compound statement
1180
1181 #ifdef _DH
1182 if (frequire && global.params.useIn)
1183 { frequire->incontract = 1;
1184 a->push(frequire);
1185 }
1186 #else
1187 if (frequire && global.params.useIn)
1188 a->push(frequire);
1189 #endif
1190
1191 // Precondition invariant
1192 if (addPreInvariant())
1193 {
1194 Expression *e = NULL;
1195 if (isDtorDeclaration())
1196 {
1197 // Call invariant directly only if it exists
1198 InvariantDeclaration *inv = ad->inv;
1199 ClassDeclaration *cd = ad->isClassDeclaration();
1200
1201 while (!inv && cd)
1202 {
1203 cd = cd->baseClass;
1204 if (!cd)
1205 break;
1206 inv = cd->inv;
1207 }
1208 if (inv)
1209 {
1210 e = new DsymbolExp(0, inv);
1211 e = new CallExp(0, e);
1212 e = e->semantic(sc2);
1213 }
1214 }
1215 else
1216 { // Call invariant virtually
1217 ThisExp *v = new ThisExp(0);
1218 v->type = vthis->type;
1219 Expression *se = new StringExp(0, (char *)"null this");
1220 se = se->semantic(sc);
1221 se->type = Type::tchar->arrayOf();
1222 e = new AssertExp(loc, v, se);
1223 }
1224 if (e)
1225 {
1226 ExpStatement *s = new ExpStatement(0, e);
1227 a->push(s);
1228 }
1229 }
1230
1231 if (fbody)
1232 a->push(fbody);
1233
1234 if (fensure)
1235 {
1236 a->push(returnLabel->statement);
1237
1238 if (type->nextOf()->ty != Tvoid)
1239 {
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);
1246 }
1247 ReturnStatement *s = new ReturnStatement(0, e);
1248 a->push(s);
1249 }
1250 }
1251
1252 fbody = new CompoundStatement(0, a);
1253
1254 /* Append destructor calls for parameters as finally blocks.
1255 */
1256 if (parameters)
1257 { for (size_t i = 0; i < parameters->dim; i++)
1258 {
1259 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1260
1261 if (v->storage_class & (STCref | STCout))
1262 continue;
1263
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.
1267 */
1268 if (v->type->toBasetype()->ty == Tsarray)
1269 continue;
1270
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);
1279 }
1280 }
1281 }
1282 }
1283
1284 sc2->callSuper = 0;
1285 sc2->pop();
1286 }
1287 semanticRun = 2;
1288 }
1289
1290 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1291 {
1292 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1293
1294 type->toCBuffer(buf, ident, hgs);
1295 bodyToCBuffer(buf, hgs);
1296 }
1297
1298
1299 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1300 {
1301 if (fbody &&
1302 (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1303 )
1304 { buf->writenl();
1305
1306 // in{}
1307 if (frequire)
1308 { buf->writestring("in");
1309 buf->writenl();
1310 frequire->toCBuffer(buf, hgs);
1311 }
1312
1313 // out{}
1314 if (fensure)
1315 { buf->writestring("out");
1316 if (outId)
1317 { buf->writebyte('(');
1318 buf->writestring(outId->toChars());
1319 buf->writebyte(')');
1320 }
1321 buf->writenl();
1322 fensure->toCBuffer(buf, hgs);
1323 }
1324
1325 if (frequire || fensure)
1326 { buf->writestring("body");
1327 buf->writenl();
1328 }
1329
1330 buf->writebyte('{');
1331 buf->writenl();
1332 fbody->toCBuffer(buf, hgs);
1333 buf->writebyte('}');
1334 buf->writenl();
1335 }
1336 else
1337 { buf->writeByte(';');
1338 buf->writenl();
1339 }
1340 }
1341
1342 /****************************************************
1343 * Determine if 'this' overrides fd.
1344 * Return !=0 if it does.
1345 */
1346
1347 int FuncDeclaration::overrides(FuncDeclaration *fd)
1348 { int result = 0;
1349
1350 if (fd->ident == ident)
1351 {
1352 int cov = type->covariant(fd->type);
1353 if (cov)
1354 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1355 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1356
1357 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1358 result = 1;
1359 }
1360 }
1361 return result;
1362 }
1363
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
1370 */
1371
1372 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
1373 {
1374 for (int vi = 0; vi < dim; vi++)
1375 {
1376 FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
1377 if (fdv && fdv->ident == ident)
1378 {
1379 int cov = type->covariant(fdv->type);
1380 //printf("\tbaseclass cov = %d\n", cov);
1381 switch (cov)
1382 {
1383 case 0: // types are distinct
1384 break;
1385
1386 case 1:
1387 return vi;
1388
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;
1396
1397 case 3:
1398 return -2; // forward references
1399
1400 default:
1401 assert(0);
1402 }
1403 }
1404 }
1405 return -1;
1406 }
1407
1408 /****************************************************
1409 * Overload this FuncDeclaration with the new one f.
1410 * Return !=0 if successful; i.e. no conflict.
1411 */
1412
1413 int FuncDeclaration::overloadInsert(Dsymbol *s)
1414 {
1415 FuncDeclaration *f;
1416 AliasDeclaration *a;
1417
1418 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1419 a = s->isAliasDeclaration();
1420 if (a)
1421 {
1422 if (overnext)
1423 return overnext->overloadInsert(a);
1424 if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1425 {
1426 //printf("\ta = '%s'\n", a->type->toChars());
1427 return FALSE;
1428 }
1429 overnext = a;
1430 //printf("\ttrue: no conflict\n");
1431 return TRUE;
1432 }
1433 f = s->isFuncDeclaration();
1434 if (!f)
1435 return FALSE;
1436
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.
1442 */
1443 if (type)
1444 { printf("type = %s\n", type->toChars());
1445 printf("f->type = %s\n", f->type->toChars());
1446 }
1447 if (type && f->type && // can be NULL for overloaded constructors
1448 f->type->covariant(type) &&
1449 f->type->mod == type->mod &&
1450 !isFuncAliasDeclaration())
1451 {
1452 //printf("\tfalse: conflict %s\n", kind());
1453 return FALSE;
1454 }
1455 #endif
1456
1457 if (overnext)
1458 return overnext->overloadInsert(f);
1459 overnext = f;
1460 //printf("\ttrue: no conflict\n");
1461 return TRUE;
1462 }
1463
1464 /********************************************
1465 * Find function in overload list that exactly matches t.
1466 */
1467
1468 /***************************************************
1469 * Visit each overloaded function in turn, and call
1470 * (*fp)(param, f) on it.
1471 * Exit when no more, or (*fp)(param, f) returns 1.
1472 * Returns:
1473 * 0 continue
1474 * 1 done
1475 */
1476
1477 int overloadApply(FuncDeclaration *fstart,
1478 int (*fp)(void *, FuncDeclaration *),
1479 void *param)
1480 {
1481 FuncDeclaration *f;
1482 Declaration *d;
1483 Declaration *next;
1484
1485 for (d = fstart; d; d = next)
1486 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1487
1488 if (fa)
1489 {
1490 if (overloadApply(fa->funcalias, fp, param))
1491 return 1;
1492 next = fa->overnext;
1493 }
1494 else
1495 {
1496 AliasDeclaration *a = d->isAliasDeclaration();
1497
1498 if (a)
1499 {
1500 Dsymbol *s = a->toAlias();
1501 next = s->isDeclaration();
1502 if (next == a)
1503 break;
1504 if (next == fstart)
1505 break;
1506 }
1507 else
1508 {
1509 f = d->isFuncDeclaration();
1510 if (!f)
1511 { d->error("is aliased to a function");
1512 break; // BUG: should print error message?
1513 }
1514 if ((*fp)(param, f))
1515 return 1;
1516
1517 next = f->overnext;
1518 }
1519 }
1520 }
1521 return 0;
1522 }
1523
1524 /********************************************
1525 * If there are no overloads of function f, return that function,
1526 * otherwise return NULL.
1527 */
1528
1529 static int fpunique(void *param, FuncDeclaration *f)
1530 { FuncDeclaration **pf = (FuncDeclaration **)param;
1531
1532 if (*pf)
1533 { *pf = NULL;
1534 return 1; // ambiguous, done
1535 }
1536 else
1537 { *pf = f;
1538 return 0;
1539 }
1540 }
1541
1542 FuncDeclaration *FuncDeclaration::isUnique()
1543 { FuncDeclaration *result = NULL;
1544
1545 overloadApply(this, &fpunique, &result);
1546 return result;
1547 }
1548
1549 /********************************************
1550 * Find function in overload list that exactly matches t.
1551 */
1552
1553 struct Param1
1554 {
1555 Type *t; // type to match
1556 FuncDeclaration *f; // return value
1557 };
1558
1559 int fp1(void *param, FuncDeclaration *f)
1560 { Param1 *p = (Param1 *)param;
1561 Type *t = p->t;
1562
1563 if (t->equals(f->type))
1564 { p->f = f;
1565 return 1;
1566 }
1567
1568 #if DMDV2
1569 /* Allow covariant matches, if it's just a const conversion
1570 * of the return type
1571 */
1572 if (t->ty == Tfunction)
1573 { TypeFunction *tf = (TypeFunction *)f->type;
1574 if (tf->covariant(t) == 1 &&
1575 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
1576 {
1577 p->f = f;
1578 return 1;
1579 }
1580 }
1581 #endif
1582 return 0;
1583 }
1584
1585 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1586 {
1587 Param1 p;
1588 p.t = t;
1589 p.f = NULL;
1590 overloadApply(this, &fp1, &p);
1591 return p.f;
1592 }
1593
1594
1595 /********************************************
1596 * Decide which function matches the arguments best.
1597 */
1598
1599 struct Param2
1600 {
1601 Match *m;
1602 Expression *ethis;
1603 Expressions *arguments;
1604 };
1605
1606 int fp2(void *param, FuncDeclaration *f)
1607 { Param2 *p = (Param2 *)param;
1608 Match *m = p->m;
1609 Expressions *arguments = p->arguments;
1610 MATCH match;
1611
1612 if (f != m->lastf) // skip duplicates
1613 {
1614 m->anyf = f;
1615 TypeFunction *tf = (TypeFunction *)f->type;
1616 match = (MATCH) tf->callMatch(f->needThis() ? p->ethis : NULL, arguments);
1617 //printf("match = %d\n", match);
1618 if (match != MATCHnomatch)
1619 {
1620 if (match > m->last)
1621 goto LfIsBetter;
1622
1623 if (match < m->last)
1624 goto LlastIsBetter;
1625
1626 /* See if one of the matches overrides the other.
1627 */
1628 if (m->lastf->overrides(f))
1629 goto LlastIsBetter;
1630 else if (f->overrides(m->lastf))
1631 goto LfIsBetter;
1632
1633 /* Try to disambiguate using template-style partial ordering rules.
1634 * In essence, if f() and g() are ambiguous, if f() can call g(),
1635 * but g() cannot call f(), then pick f().
1636 * This is because f() is "more specialized."
1637 */
1638 {
1639 MATCH c1 = f->leastAsSpecialized(m->lastf);
1640 MATCH c2 = m->lastf->leastAsSpecialized(f);
1641 //printf("c1 = %d, c2 = %d\n", c1, c2);
1642 if (c1 > c2)
1643 goto LfIsBetter;
1644 if (c1 < c2)
1645 goto LlastIsBetter;
1646 }
1647
1648 Lambiguous:
1649 m->nextf = f;
1650 m->count++;
1651 return 0;
1652
1653 LfIsBetter:
1654 m->last = match;
1655 m->lastf = f;
1656 m->count = 1;
1657 return 0;
1658
1659 LlastIsBetter:
1660 return 0;
1661 }
1662 }
1663 return 0;
1664 }
1665
1666 void overloadResolveX(Match *m, FuncDeclaration *fstart,
1667 Expression *ethis, Expressions *arguments)
1668 {
1669 Param2 p;
1670 p.m = m;
1671 p.ethis = ethis;
1672 p.arguments = arguments;
1673 overloadApply(fstart, &fp2, &p);
1674 }
1675
1676
1677 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags)
1678 {
1679 TypeFunction *tf;
1680 Match m;
1681
1682 #if 0
1683 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1684 if (arguments)
1685 { int i;
1686
1687 for (i = 0; i < arguments->dim; i++)
1688 { Expression *arg;
1689
1690 arg = (Expression *)arguments->data[i];
1691 assert(arg->type);
1692 printf("\t%s: ", arg->toChars());
1693 arg->type->print();
1694 }
1695 }
1696 #endif
1697
1698 memset(&m, 0, sizeof(m));
1699 m.last = MATCHnomatch;
1700 overloadResolveX(&m, this, ethis, arguments);
1701
1702 if (m.count == 1) // exactly one match
1703 {
1704 return m.lastf;
1705 }
1706 else
1707 {
1708 OutBuffer buf;
1709
1710 if (arguments)
1711 {
1712 HdrGenState hgs;
1713
1714 argExpTypesToCBuffer(&buf, arguments, &hgs);
1715 }
1716
1717 if (m.last == MATCHnomatch)
1718 {
1719 if (flags & 1) // if do not print error messages
1720 return NULL; // no match
1721
1722 tf = (TypeFunction *)type;
1723
1724 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1725 error(loc, "%s does not match parameter types (%s)",
1726 Argument::argsTypesToChars(tf->parameters, tf->varargs),
1727 buf.toChars());
1728 return m.anyf; // as long as it's not a FuncAliasDeclaration
1729 }
1730 else
1731 {
1732 #if 1
1733 TypeFunction *t1 = (TypeFunction *)m.lastf->type;
1734 TypeFunction *t2 = (TypeFunction *)m.nextf->type;
1735
1736 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1737 buf.toChars(),
1738 m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
1739 m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
1740 #else
1741 error(loc, "overloads %s and %s both match argument list for %s",
1742 m.lastf->type->toChars(),
1743 m.nextf->type->toChars(),
1744 m.lastf->toChars());
1745 #endif
1746 return m.lastf;
1747 }
1748 }
1749 }
1750
1751 /*************************************
1752 * Determine partial specialization order of 'this' vs g.
1753 * This is very similar to TemplateDeclaration::leastAsSpecialized().
1754 * Returns:
1755 * match 'this' is at least as specialized as g
1756 * 0 g is more specialized than 'this'
1757 */
1758
1759 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
1760 {
1761 #define LOG_LEASTAS 0
1762
1763 #if LOG_LEASTAS
1764 printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
1765 #endif
1766
1767 /* This works by calling g() with f()'s parameters, and
1768 * if that is possible, then f() is at least as specialized
1769 * as g() is.
1770 */
1771
1772 TypeFunction *tf = (TypeFunction *)type;
1773 TypeFunction *tg = (TypeFunction *)g->type;
1774 size_t nfparams = Argument::dim(tf->parameters);
1775 size_t ngparams = Argument::dim(tg->parameters);
1776 MATCH match = MATCHexact;
1777
1778 /* If both functions have a 'this' pointer, and the mods are not
1779 * the same and g's is not const, then this is less specialized.
1780 */
1781 if (needThis() && g->needThis())
1782 {
1783 if (tf->mod != tg->mod)
1784 {
1785 if (tg->mod == MODconst)
1786 match = MATCHconst;
1787 else
1788 return MATCHnomatch;
1789 }
1790 }
1791
1792 /* Create a dummy array of arguments out of the parameters to f()
1793 */
1794 Expressions args;
1795 args.setDim(nfparams);
1796 for (int u = 0; u < nfparams; u++)
1797 {
1798 Argument *p = Argument::getNth(tf->parameters, u);
1799 Expression *e;
1800 if (p->storageClass & (STCref | STCout))
1801 {
1802 e = new IdentifierExp(0, p->ident);
1803 e->type = p->type;
1804 }
1805 else
1806 e = p->type->defaultInit();
1807 args.data[u] = e;
1808 }
1809
1810 MATCH m = (MATCH) tg->callMatch(NULL, &args);
1811 if (m)
1812 {
1813 /* A variadic parameter list is less specialized than a
1814 * non-variadic one.
1815 */
1816 if (tf->varargs && !tg->varargs)
1817 goto L1; // less specialized
1818
1819 #if LOG_LEASTAS
1820 printf(" matches %d, so is least as specialized\n", m);
1821 #endif
1822 return m;
1823 }
1824 L1:
1825 #if LOG_LEASTAS
1826 printf(" doesn't match, so is not as specialized\n");
1827 #endif
1828 return MATCHnomatch;
1829 }
1830
1831 /********************************
1832 * Labels are in a separate scope, one per function.
1833 */
1834
1835 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
1836 { Dsymbol *s;
1837
1838 if (!labtab)
1839 labtab = new DsymbolTable(); // guess we need one
1840
1841 s = labtab->lookup(ident);
1842 if (!s)
1843 {
1844 s = new LabelDsymbol(ident);
1845 labtab->insert(s);
1846 }
1847 return (LabelDsymbol *)s;
1848 }
1849
1850 /****************************************
1851 * If non-static member function that has a 'this' pointer,
1852 * return the aggregate it is a member of.
1853 * Otherwise, return NULL.
1854 */
1855
1856 AggregateDeclaration *FuncDeclaration::isThis()
1857 { AggregateDeclaration *ad;
1858
1859 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1860 ad = NULL;
1861 if ((storage_class & STCstatic) == 0)
1862 {
1863 ad = isMember2();
1864 }
1865 //printf("-FuncDeclaration::isThis() %p\n", ad);
1866 return ad;
1867 }
1868
1869 AggregateDeclaration *FuncDeclaration::isMember2()
1870 { AggregateDeclaration *ad;
1871
1872 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1873 ad = NULL;
1874 for (Dsymbol *s = this; s; s = s->parent)
1875 {
1876 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1877 ad = s->isMember();
1878 if (ad)
1879 { //printf("test4\n");
1880 break;
1881 }
1882 if (!s->parent ||
1883 (!s->parent->isTemplateInstance()))
1884 { //printf("test5\n");
1885 break;
1886 }
1887 }
1888 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1889 return ad;
1890 }
1891
1892 /*****************************************
1893 * Determine lexical level difference from 'this' to nested function 'fd'.
1894 * Error if this cannot call fd.
1895 * Returns:
1896 * 0 same level
1897 * -1 increase nesting by 1 (fd is nested within 'this')
1898 * >0 decrease nesting by number
1899 */
1900
1901 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
1902 { int level;
1903 Dsymbol *s;
1904 Dsymbol *fdparent;
1905
1906 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1907 fdparent = fd->toParent2();
1908 if (fdparent == this)
1909 return -1;
1910 s = this;
1911 level = 0;
1912 while (fd != s && fdparent != s->toParent2())
1913 {
1914 //printf("\ts = '%s'\n", s->toChars());
1915 FuncDeclaration *thisfd = s->isFuncDeclaration();
1916 if (thisfd)
1917 { if (!thisfd->isNested() && !thisfd->vthis)
1918 goto Lerr;
1919 }
1920 else
1921 {
1922 ClassDeclaration *thiscd = s->isClassDeclaration();
1923 if (thiscd)
1924 { if (!thiscd->isNested())
1925 goto Lerr;
1926 }
1927 else
1928 goto Lerr;
1929 }
1930
1931 s = s->toParent2();
1932 assert(s);
1933 level++;
1934 }
1935 return level;
1936
1937 Lerr:
1938 error(loc, "cannot access frame of function %s", fd->toChars());
1939 return 1;
1940 }
1941
1942 void FuncDeclaration::appendExp(Expression *e)
1943 { Statement *s;
1944
1945 s = new ExpStatement(0, e);
1946 appendState(s);
1947 }
1948
1949 void FuncDeclaration::appendState(Statement *s)
1950 { CompoundStatement *cs;
1951
1952 if (!fbody)
1953 { Statements *a;
1954
1955 a = new Statements();
1956 fbody = new CompoundStatement(0, a);
1957 }
1958 cs = fbody->isCompoundStatement();
1959 cs->statements->push(s);
1960 }
1961
1962
1963 int FuncDeclaration::isMain()
1964 {
1965 return ident == Id::main &&
1966 linkage != LINKc && !isMember() && !isNested();
1967 }
1968
1969 int FuncDeclaration::isWinMain()
1970 {
1971 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
1972 #if 0
1973 int x = ident == Id::WinMain &&
1974 linkage != LINKc && !isMember();
1975 printf("%s\n", x ? "yes" : "no");
1976 return x;
1977 #else
1978 return ident == Id::WinMain &&
1979 linkage != LINKc && !isMember();
1980 #endif
1981 }
1982
1983 int FuncDeclaration::isDllMain()
1984 {
1985 return ident == Id::DllMain &&
1986 linkage != LINKc && !isMember();
1987 }
1988
1989 int FuncDeclaration::isExport()
1990 {
1991 return protection == PROTexport;
1992 }
1993
1994 int FuncDeclaration::isImportedSymbol()
1995 {
1996 //printf("isImportedSymbol()\n");
1997 //printf("protection = %d\n", protection);
1998 return (protection == PROTexport) && !fbody;
1999 }
2000
2001 // Determine if function goes into virtual function pointer table
2002
2003 int FuncDeclaration::isVirtual()
2004 {
2005 #if 0
2006 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
2007 printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2008 printf("result is %d\n",
2009 isMember() &&
2010 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2011 toParent()->isClassDeclaration());
2012 #endif
2013 return isMember() &&
2014 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2015 toParent()->isClassDeclaration();
2016 }
2017
2018 int FuncDeclaration::isFinal()
2019 {
2020 #if 0
2021 printf("FuncDeclaration::isFinal(%s)\n", toChars());
2022 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2023 printf("result is %d\n",
2024 isMember() &&
2025 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2026 toParent()->isClassDeclaration());
2027 #endif
2028 ClassDeclaration *cd;
2029 return isMember() &&
2030 (Declaration::isFinal() ||
2031 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2032 }
2033
2034 int FuncDeclaration::isAbstract()
2035 {
2036 return storage_class & STCabstract;
2037 }
2038
2039 int FuncDeclaration::isCodeseg()
2040 {
2041 return TRUE; // functions are always in the code segment
2042 }
2043
2044 int FuncDeclaration::isOverloadable()
2045 {
2046 return 1; // functions can be overloaded
2047 }
2048
2049 // Determine if function needs
2050 // a static frame pointer to its lexically enclosing function
2051
2052 int FuncDeclaration::isNested()
2053 {
2054 //if (!toParent())
2055 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2056 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2057 return ((storage_class & STCstatic) == 0) &&
2058 (toParent2()->isFuncDeclaration() != NULL);
2059 }
2060
2061 int FuncDeclaration::needThis()
2062 {
2063 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2064 int i = isThis() != NULL;
2065 //printf("\t%d\n", i);
2066 if (!i && isFuncAliasDeclaration())
2067 i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
2068 return i;
2069 }
2070
2071 int FuncDeclaration::addPreInvariant()
2072 {
2073 AggregateDeclaration *ad = isThis();
2074 return (ad &&
2075 //ad->isClassDeclaration() &&
2076 global.params.useInvariants &&
2077 (protection == PROTpublic || protection == PROTexport) &&
2078 !naked &&
2079 ident != Id::cpctor);
2080 }
2081
2082 int FuncDeclaration::addPostInvariant()
2083 {
2084 AggregateDeclaration *ad = isThis();
2085 return (ad &&
2086 ad->inv &&
2087 //ad->isClassDeclaration() &&
2088 global.params.useInvariants &&
2089 (protection == PROTpublic || protection == PROTexport) &&
2090 !naked &&
2091 ident != Id::cpctor);
2092 }
2093
2094 /**********************************
2095 * Generate a FuncDeclaration for a runtime library function.
2096 */
2097
2098 //
2099 // LDC: Adjusted to give argument info to the runtime function decl.
2100 //
2101
2102 FuncDeclaration *FuncDeclaration::genCfunc(Arguments *args, Type *treturn, const char *name)
2103 {
2104 return genCfunc(args, treturn, Lexer::idPool(name));
2105 }
2106
2107 FuncDeclaration *FuncDeclaration::genCfunc(Arguments *args, Type *treturn, Identifier *id)
2108 {
2109 FuncDeclaration *fd;
2110 TypeFunction *tf;
2111 Dsymbol *s;
2112 static DsymbolTable *st = NULL;
2113
2114 //printf("genCfunc(name = '%s')\n", id->toChars());
2115 //printf("treturn\n\t"); treturn->print();
2116
2117 // See if already in table
2118 if (!st)
2119 st = new DsymbolTable();
2120 s = st->lookup(id);
2121 if (s)
2122 {
2123 fd = s->isFuncDeclaration();
2124 assert(fd);
2125 assert(fd->type->nextOf()->equals(treturn));
2126 }
2127 else
2128 {
2129 tf = new TypeFunction(args, treturn, 0, LINKc);
2130 fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2131 fd->protection = PROTpublic;
2132 fd->linkage = LINKc;
2133
2134 st->insert(fd);
2135 }
2136 return fd;
2137 }
2138
2139 const char *FuncDeclaration::kind()
2140 {
2141 return "function";
2142 }
2143
2144 /*******************************
2145 * Look at all the variables in this function that are referenced
2146 * by nested functions, and determine if a closure needs to be
2147 * created for them.
2148 */
2149
2150 #if DMDV2
2151 int FuncDeclaration::needsClosure()
2152 {
2153 /* Need a closure for all the closureVars[] if any of the
2154 * closureVars[] are accessed by a
2155 * function that escapes the scope of this function.
2156 * We take the conservative approach and decide that any function that:
2157 * 1) is a virtual function
2158 * 2) has its address taken
2159 * 3) has a parent that escapes
2160 *
2161 * Note that since a non-virtual function can be called by
2162 * a virtual one, if that non-virtual function accesses a closure
2163 * var, the closure still has to be taken. Hence, we check for isThis()
2164 * instead of isVirtual(). (thanks to David Friedman)
2165 */
2166
2167 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2168 for (int i = 0; i < closureVars.dim; i++)
2169 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
2170 assert(v->isVarDeclaration());
2171 //printf("\tv = %s\n", v->toChars());
2172
2173 for (int j = 0; j < v->nestedrefs.dim; j++)
2174 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
2175 assert(f != this);
2176
2177 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2178 if (f->isThis() || f->tookAddressOf)
2179 goto Lyes; // assume f escapes this function's scope
2180
2181 // Look to see if any parents of f that are below this escape
2182 for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
2183 {
2184 f = s->isFuncDeclaration();
2185 if (f && (f->isThis() || f->tookAddressOf))
2186 goto Lyes;
2187 }
2188 }
2189 }
2190 return 0;
2191
2192 Lyes:
2193 //printf("\tneeds closure\n");
2194 return 1;
2195 }
2196 #endif
2197
2198 /****************************** FuncAliasDeclaration ************************/
2199
2200 // Used as a way to import a set of functions from another scope into this one.
2201
2202 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2203 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2204 (enum STC)funcalias->storage_class, funcalias->type)
2205 {
2206 assert(funcalias != this);
2207 this->funcalias = funcalias;
2208 }
2209
2210 const char *FuncAliasDeclaration::kind()
2211 {
2212 return "function alias";
2213 }
2214
2215
2216 /****************************** FuncLiteralDeclaration ************************/
2217
2218 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2219 enum TOK tok, ForeachStatement *fes)
2220 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2221 {
2222 const char *id;
2223
2224 if (fes)
2225 id = "__foreachbody";
2226 else if (tok == TOKdelegate)
2227 id = "__dgliteral";
2228 else
2229 id = "__funcliteral";
2230 this->ident = Identifier::generateId(id);
2231 this->tok = tok;
2232 this->fes = fes;
2233 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2234 }
2235
2236 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2237 {
2238 FuncLiteralDeclaration *f;
2239
2240 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2241 if (s)
2242 f = (FuncLiteralDeclaration *)s;
2243 else
2244 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2245 FuncDeclaration::syntaxCopy(f);
2246 return f;
2247 }
2248
2249 int FuncLiteralDeclaration::isNested()
2250 {
2251 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2252 return (tok == TOKdelegate);
2253 }
2254
2255 int FuncLiteralDeclaration::isVirtual()
2256 {
2257 return FALSE;
2258 }
2259
2260 const char *FuncLiteralDeclaration::kind()
2261 {
2262 // GCC requires the (char*) casts
2263 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
2264 }
2265
2266 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2267 {
2268 static Identifier *idfunc;
2269 static Identifier *iddel;
2270
2271 if (!idfunc)
2272 idfunc = new Identifier("function", 0);
2273 if (!iddel)
2274 iddel = new Identifier("delegate", 0);
2275
2276 type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
2277 bodyToCBuffer(buf, hgs);
2278 }
2279
2280
2281 /********************************* CtorDeclaration ****************************/
2282
2283 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2284 : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
2285 {
2286 this->arguments = arguments;
2287 this->varargs = varargs;
2288 //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
2289 }
2290
2291 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2292 {
2293 CtorDeclaration *f;
2294
2295 f = new CtorDeclaration(loc, endloc, NULL, varargs);
2296
2297 f->outId = outId;
2298 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2299 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
2300 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
2301 assert(!fthrows); // deprecated
2302
2303 f->arguments = Argument::arraySyntaxCopy(arguments);
2304 return f;
2305 }
2306
2307
2308 void CtorDeclaration::semantic(Scope *sc)
2309 {
2310 AggregateDeclaration *ad;
2311 Type *tret;
2312
2313 //printf("CtorDeclaration::semantic()\n");
2314 if (type)
2315 return;
2316
2317 sc = sc->push();
2318 sc->stc &= ~STCstatic; // not a static constructor
2319
2320 parent = sc->parent;
2321 Dsymbol *parent = toParent();
2322 ad = parent->isAggregateDeclaration();
2323 if (!ad || parent->isUnionDeclaration())
2324 {
2325 error("constructors are only for class or struct definitions");
2326 fatal();
2327 tret = Type::tvoid;
2328 }
2329 else
2330 { tret = ad->handle;
2331 assert(tret);
2332 }
2333 type = new TypeFunction(arguments, tret, varargs, LINKd);
2334 if (!originalType)
2335 originalType = type;
2336
2337 sc->flags |= SCOPEctor;
2338 type = type->semantic(loc, sc);
2339 sc->flags &= ~SCOPEctor;
2340
2341 // Append:
2342 // return this;
2343 // to the function body
2344 if (fbody)
2345 {
2346 Expression *e = new ThisExp(0);
2347 Statement *s = new ReturnStatement(0, e);
2348 fbody = new CompoundStatement(0, fbody, s);
2349 }
2350
2351 FuncDeclaration::semantic(sc);
2352
2353 sc->pop();
2354
2355 // See if it's the default constructor
2356 if (ad && varargs == 0 && Argument::dim(arguments) == 0)
2357 { if (ad->isStructDeclaration())
2358 error("default constructor not allowed for structs");
2359 else
2360 ad->defaultCtor = this;
2361 }
2362 }
2363
2364 const char *CtorDeclaration::kind()
2365 {
2366 return "constructor";
2367 }
2368
2369 char *CtorDeclaration::toChars()
2370 {
2371 return (char *)"this";
2372 }
2373
2374 int CtorDeclaration::isVirtual()
2375 {
2376 return FALSE;
2377 }
2378
2379 int CtorDeclaration::addPreInvariant()
2380 {
2381 return FALSE;
2382 }
2383
2384 int CtorDeclaration::addPostInvariant()
2385 {
2386 return (vthis && global.params.useInvariants);
2387 }
2388
2389
2390 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2391 {
2392 buf->writestring("this");
2393 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2394 bodyToCBuffer(buf, hgs);
2395 }
2396
2397 /********************************* PostBlitDeclaration ****************************/
2398
2399 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
2400 : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
2401 {
2402 }
2403
2404 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
2405 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2406 {
2407 }
2408
2409 Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
2410 {
2411 assert(!s);
2412 PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
2413 return FuncDeclaration::syntaxCopy(dd);
2414 }
2415
2416
2417 void PostBlitDeclaration::semantic(Scope *sc)
2418 {
2419 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2420 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2421 parent = sc->parent;
2422 Dsymbol *parent = toParent();
2423 StructDeclaration *ad = parent->isStructDeclaration();
2424 if (!ad)
2425 {
2426 error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2427 }
2428 else if (ident == Id::_postblit)
2429 ad->postblits.push(this);
2430 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2431
2432 sc = sc->push();
2433 sc->stc &= ~STCstatic; // not static
2434 sc->linkage = LINKd;
2435
2436 FuncDeclaration::semantic(sc);
2437
2438 sc->pop();
2439 }
2440
2441 int PostBlitDeclaration::overloadInsert(Dsymbol *s)
2442 {
2443 return FALSE; // cannot overload postblits
2444 }
2445
2446 int PostBlitDeclaration::addPreInvariant()
2447 {
2448 return FALSE;
2449 }
2450
2451 int PostBlitDeclaration::addPostInvariant()
2452 {
2453 return (vthis && global.params.useInvariants);
2454 }
2455
2456 int PostBlitDeclaration::isVirtual()
2457 {
2458 return FALSE;
2459 }
2460
2461 void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2462 {
2463 if (hgs->hdrgen)
2464 return;
2465 buf->writestring("=this()");
2466 bodyToCBuffer(buf, hgs);
2467 }
2468
2469 /********************************* DtorDeclaration ****************************/
2470
2471 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
2472 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
2473 {
2474 }
2475
2476 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
2477 : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
2478 {
2479 }
2480
2481 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
2482 {
2483 assert(!s);
2484 DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
2485 return FuncDeclaration::syntaxCopy(dd);
2486 }
2487
2488
2489 void DtorDeclaration::semantic(Scope *sc)
2490 {
2491 //printf("DtorDeclaration::semantic() %s\n", toChars());
2492 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2493 parent = sc->parent;
2494 Dsymbol *parent = toParent();
2495 AggregateDeclaration *ad = parent->isAggregateDeclaration();
2496 if (!ad)
2497 {
2498 error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
2499 fatal();
2500 }
2501 else if (ident == Id::dtor)
2502 ad->dtors.push(this);
2503 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2504
2505 sc = sc->push();
2506 sc->stc &= ~STCstatic; // not a static destructor
2507 sc->linkage = LINKd;
2508
2509 FuncDeclaration::semantic(sc);
2510
2511 sc->pop();
2512 }
2513
2514 int DtorDeclaration::overloadInsert(Dsymbol *s)
2515 {
2516 return FALSE; // cannot overload destructors
2517 }
2518
2519 int DtorDeclaration::addPreInvariant()
2520 {
2521 return (vthis && global.params.useInvariants);
2522 }
2523
2524 int DtorDeclaration::addPostInvariant()
2525 {
2526 return FALSE;
2527 }
2528
2529 int DtorDeclaration::isVirtual()
2530 {
2531 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2532 * but doing so will require recompiling everything.
2533 */
2534 #if BREAKABI
2535 return FALSE;
2536 #else
2537 return FuncDeclaration::isVirtual();
2538 #endif
2539 }
2540
2541 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2542 {
2543 if (hgs->hdrgen)
2544 return;
2545 buf->writestring("~this()");
2546 bodyToCBuffer(buf, hgs);
2547 }
2548
2549 /********************************* StaticCtorDeclaration ****************************/
2550
2551 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
2552 : FuncDeclaration(loc, endloc,
2553 Identifier::generateId("_staticCtor"), STCstatic, NULL)
2554 {
2555 }
2556
2557 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
2558 {
2559 StaticCtorDeclaration *scd;
2560
2561 assert(!s);
2562 scd = new StaticCtorDeclaration(loc, endloc);
2563 return FuncDeclaration::syntaxCopy(scd);
2564 }
2565
2566
2567 void StaticCtorDeclaration::semantic(Scope *sc)
2568 {
2569 //printf("StaticCtorDeclaration::semantic()\n");
2570
2571 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2572
2573 /* If the static ctor appears within a template instantiation,
2574 * it could get called multiple times by the module constructors
2575 * for different modules. Thus, protect it with a gate.
2576 */
2577 if (inTemplateInstance())
2578 {
2579 /* Add this prefix to the function:
2580 * static int gate;
2581 * if (++gate != 1) return;
2582 * Note that this is not thread safe; should not have threads
2583 * during static construction.
2584 */
2585 Identifier *id = Lexer::idPool("__gate");
2586 VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
2587 v->storage_class = STCstatic;
2588 Statements *sa = new Statements();
2589 Statement *s = new DeclarationStatement(0, v);
2590 sa->push(s);
2591 Expression *e = new IdentifierExp(0, id);
2592 e = new AddAssignExp(0, e, new IntegerExp(1));
2593 e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
2594 s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
2595 sa->push(s);
2596 if (fbody)
2597 sa->push(fbody);
2598 fbody = new CompoundStatement(0, sa);
2599 }
2600
2601 FuncDeclaration::semantic(sc);
2602
2603 // We're going to need ModuleInfo
2604 Module *m = getModule();
2605 if (!m)
2606 m = sc->module;
2607 if (m)
2608 { m->needmoduleinfo = 1;
2609 #ifdef IN_GCC
2610 m->strictlyneedmoduleinfo = 1;
2611 #endif
2612 }
2613 }
2614
2615 AggregateDeclaration *StaticCtorDeclaration::isThis()
2616 {
2617 return NULL;
2618 }
2619
2620 int StaticCtorDeclaration::isStaticConstructor()
2621 {
2622 return TRUE;
2623 }
2624
2625 int StaticCtorDeclaration::isVirtual()
2626 {
2627 return FALSE;
2628 }
2629
2630 int StaticCtorDeclaration::addPreInvariant()
2631 {
2632 return FALSE;
2633 }
2634
2635 int StaticCtorDeclaration::addPostInvariant()
2636 {
2637 return FALSE;
2638 }
2639
2640 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2641 {
2642 if (hgs->hdrgen)
2643 { buf->writestring("static this();\n");
2644 return;
2645 }
2646 buf->writestring("static this()");
2647 bodyToCBuffer(buf, hgs);
2648 }
2649
2650 /********************************* StaticDtorDeclaration ****************************/
2651
2652 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
2653 : FuncDeclaration(loc, endloc,
2654 Identifier::generateId("_staticDtor"), STCstatic, NULL)
2655 {
2656 vgate = NULL;
2657 }
2658
2659 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
2660 {
2661 StaticDtorDeclaration *sdd;
2662
2663 assert(!s);
2664 sdd = new StaticDtorDeclaration(loc, endloc);
2665 return FuncDeclaration::syntaxCopy(sdd);
2666 }
2667
2668
2669 void StaticDtorDeclaration::semantic(Scope *sc)
2670 {
2671 ClassDeclaration *cd;
2672 Type *tret;
2673
2674 cd = sc->scopesym->isClassDeclaration();
2675 if (!cd)
2676 {
2677 }
2678 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2679
2680 /* If the static ctor appears within a template instantiation,
2681 * it could get called multiple times by the module constructors
2682 * for different modules. Thus, protect it with a gate.
2683 */
2684 if (inTemplateInstance())
2685 {
2686 /* Add this prefix to the function:
2687 * static int gate;
2688 * if (--gate != 0) return;
2689 * Increment gate during constructor execution.
2690 * Note that this is not thread safe; should not have threads
2691 * during static destruction.
2692 */
2693 Identifier *id = Lexer::idPool("__gate");
2694 VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
2695 v->storage_class = STCstatic;
2696 Statements *sa = new Statements();
2697 Statement *s = new DeclarationStatement(0, v);
2698 sa->push(s);
2699 Expression *e = new IdentifierExp(0, id);
2700 e = new AddAssignExp(0, e, new IntegerExp(-1));
2701 e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0));
2702 s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
2703 sa->push(s);
2704 if (fbody)
2705 sa->push(fbody);
2706 fbody = new CompoundStatement(0, sa);
2707 vgate = v;
2708 }
2709
2710 FuncDeclaration::semantic(sc);
2711
2712 // We're going to need ModuleInfo
2713 Module *m = getModule();
2714 if (!m)
2715 m = sc->module;
2716 if (m)
2717 { m->needmoduleinfo = 1;
2718 #ifdef IN_GCC
2719 m->strictlyneedmoduleinfo = 1;
2720 #endif
2721 }
2722 }
2723
2724 AggregateDeclaration *StaticDtorDeclaration::isThis()
2725 {
2726 return NULL;
2727 }
2728
2729 int StaticDtorDeclaration::isStaticDestructor()
2730 {
2731 return TRUE;
2732 }
2733
2734 int StaticDtorDeclaration::isVirtual()
2735 {
2736 return FALSE;
2737 }
2738
2739 int StaticDtorDeclaration::addPreInvariant()
2740 {
2741 return FALSE;
2742 }
2743
2744 int StaticDtorDeclaration::addPostInvariant()
2745 {
2746 return FALSE;
2747 }
2748
2749 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2750 {
2751 if (hgs->hdrgen)
2752 return;
2753 buf->writestring("static ~this()");
2754 bodyToCBuffer(buf, hgs);
2755 }
2756
2757 /********************************* InvariantDeclaration ****************************/
2758
2759 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
2760 : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
2761 {
2762 }
2763
2764 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
2765 {
2766 InvariantDeclaration *id;
2767
2768 assert(!s);
2769 id = new InvariantDeclaration(loc, endloc);
2770 FuncDeclaration::syntaxCopy(id);
2771 return id;
2772 }
2773
2774
2775 void InvariantDeclaration::semantic(Scope *sc)
2776 {
2777 AggregateDeclaration *ad;
2778 Type *tret;
2779
2780 parent = sc->parent;
2781 Dsymbol *parent = toParent();
2782 ad = parent->isAggregateDeclaration();
2783 if (!ad)
2784 {
2785 error("invariants only are for struct/union/class definitions");
2786 return;
2787 }
2788 else if (ad->inv && ad->inv != this)
2789 {
2790 error("more than one invariant for %s", ad->toChars());
2791 }
2792 ad->inv = this;
2793 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2794
2795 sc = sc->push();
2796 sc->stc &= ~STCstatic; // not a static invariant
2797 sc->incontract++;
2798 sc->linkage = LINKd;
2799
2800 FuncDeclaration::semantic(sc);
2801
2802 sc->pop();
2803 }
2804
2805 int InvariantDeclaration::isVirtual()
2806 {
2807 return FALSE;
2808 }
2809
2810 int InvariantDeclaration::addPreInvariant()
2811 {
2812 return FALSE;
2813 }
2814
2815 int InvariantDeclaration::addPostInvariant()
2816 {
2817 return FALSE;
2818 }
2819
2820 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2821 {
2822 if (hgs->hdrgen)
2823 return;
2824 buf->writestring("invariant");
2825 bodyToCBuffer(buf, hgs);
2826 }
2827
2828
2829 /********************************* UnitTestDeclaration ****************************/
2830
2831 /*******************************
2832 * Generate unique unittest function Id so we can have multiple
2833 * instances per module.
2834 */
2835
2836 static Identifier *unitTestId()
2837 {
2838 return Lexer::uniqueId("__unittest");
2839 }
2840
2841 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
2842 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
2843 {
2844 }
2845
2846 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
2847 {
2848 UnitTestDeclaration *utd;
2849
2850 assert(!s);
2851 utd = new UnitTestDeclaration(loc, endloc);
2852 return FuncDeclaration::syntaxCopy(utd);
2853 }
2854
2855
2856 void UnitTestDeclaration::semantic(Scope *sc)
2857 {
2858 if (global.params.useUnitTests)
2859 {
2860 Type *tret;
2861
2862 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
2863 FuncDeclaration::semantic(sc);
2864 }
2865
2866 // We're going to need ModuleInfo even if the unit tests are not
2867 // compiled in, because other modules may import this module and refer
2868 // to this ModuleInfo.
2869 Module *m = getModule();
2870 if (!m)
2871 m = sc->module;
2872 if (m)
2873 m->needmoduleinfo = 1;
2874 }
2875
2876 AggregateDeclaration *UnitTestDeclaration::isThis()
2877 {
2878 return NULL;
2879 }
2880
2881 int UnitTestDeclaration::isVirtual()
2882 {
2883 return FALSE;
2884 }
2885
2886 int UnitTestDeclaration::addPreInvariant()
2887 {
2888 return FALSE;
2889 }
2890
2891 int UnitTestDeclaration::addPostInvariant()
2892 {
2893 return FALSE;
2894 }
2895
2896 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2897 {
2898 if (hgs->hdrgen)
2899 return;
2900 buf->writestring("unittest");
2901 bodyToCBuffer(buf, hgs);
2902 }
2903
2904 /********************************* NewDeclaration ****************************/
2905
2906 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
2907 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
2908 {
2909 this->arguments = arguments;
2910 this->varargs = varargs;
2911 }
2912
2913 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
2914 {
2915 NewDeclaration *f;
2916
2917 f = new NewDeclaration(loc, endloc, NULL, varargs);
2918
2919 FuncDeclaration::syntaxCopy(f);
2920
2921 f->arguments = Argument::arraySyntaxCopy(arguments);
2922
2923 return f;
2924 }
2925
2926
2927 void NewDeclaration::semantic(Scope *sc)
2928 {
2929 ClassDeclaration *cd;
2930 Type *tret;
2931
2932 //printf("NewDeclaration::semantic()\n");
2933
2934 parent = sc->parent;
2935 Dsymbol *parent = toParent();
2936 cd = parent->isClassDeclaration();
2937 if (!cd && !parent->isStructDeclaration())
2938 {
2939 error("new allocators only are for class or struct definitions");
2940 }
2941 tret = Type::tvoid->pointerTo();
2942 type = new TypeFunction(arguments, tret, varargs, LINKd);
2943
2944 type = type->semantic(loc, sc);
2945 assert(type->ty == Tfunction);
2946
2947 // Check that there is at least one argument of type uint
2948 TypeFunction *tf = (TypeFunction *)type;
2949 if (Argument::dim(tf->parameters) < 1)
2950 {
2951 error("at least one argument of type uint expected");
2952 }
2953 else
2954 {
2955 Argument *a = Argument::getNth(tf->parameters, 0);
2956 if (!a->type->equals(Type::tuns32))
2957 error("first argument must be type uint, not %s", a->type->toChars());
2958 }
2959
2960 FuncDeclaration::semantic(sc);
2961 }
2962
2963 const char *NewDeclaration::kind()
2964 {
2965 return "allocator";
2966 }
2967
2968 int NewDeclaration::isVirtual()
2969 {
2970 return FALSE;
2971 }
2972
2973 int NewDeclaration::addPreInvariant()
2974 {
2975 return FALSE;
2976 }
2977
2978 int NewDeclaration::addPostInvariant()
2979 {
2980 return FALSE;
2981 }
2982
2983 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2984 {
2985 buf->writestring("new");
2986 Argument::argsToCBuffer(buf, hgs, arguments, varargs);
2987 bodyToCBuffer(buf, hgs);
2988 }
2989
2990
2991 /********************************* DeleteDeclaration ****************************/
2992
2993 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
2994 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
2995 {
2996 this->arguments = arguments;
2997 }
2998
2999 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
3000 {
3001 DeleteDeclaration *f;
3002
3003 f = new DeleteDeclaration(loc, endloc, NULL);
3004
3005 FuncDeclaration::syntaxCopy(f);
3006
3007 f->arguments = Argument::arraySyntaxCopy(arguments);
3008
3009 return f;
3010 }
3011
3012
3013 void DeleteDeclaration::semantic(Scope *sc)
3014 {
3015 ClassDeclaration *cd;
3016
3017 //printf("DeleteDeclaration::semantic()\n");
3018
3019 parent = sc->parent;
3020 Dsymbol *parent = toParent();
3021 cd = parent->isClassDeclaration();
3022 if (!cd && !parent->isStructDeclaration())
3023 {
3024 error("new allocators only are for class or struct definitions");
3025 }
3026 type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
3027
3028 type = type->semantic(loc, sc);
3029 assert(type->ty == Tfunction);
3030
3031 // Check that there is only one argument of type void*
3032 TypeFunction *tf = (TypeFunction *)type;
3033 if (Argument::dim(tf->parameters) != 1)
3034 {
3035 error("one argument of type void* expected");
3036 }
3037 else
3038 {
3039 Argument *a = Argument::getNth(tf->parameters, 0);
3040 if (!a->type->equals(Type::tvoid->pointerTo()))
3041 error("one argument of type void* expected, not %s", a->type->toChars());
3042 }
3043
3044 FuncDeclaration::semantic(sc);
3045 }
3046
3047 const char *DeleteDeclaration::kind()
3048 {
3049 return "deallocator";
3050 }
3051
3052 int DeleteDeclaration::isDelete()
3053 {
3054 return TRUE;
3055 }
3056
3057 int DeleteDeclaration::isVirtual()
3058 {
3059 return FALSE;
3060 }
3061
3062 int DeleteDeclaration::addPreInvariant()
3063 {
3064 return FALSE;
3065 }
3066
3067 int DeleteDeclaration::addPostInvariant()
3068 {
3069 return FALSE;
3070 }
3071
3072 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3073 {
3074 buf->writestring("delete");
3075 Argument::argsToCBuffer(buf, hgs, arguments, 0);
3076 bodyToCBuffer(buf, hgs);
3077 }
3078
3079
3080
3081