root/trunk/src/func.c

Revision 812, 111.7 kB (checked in by walter, 1 year ago)

harmonize some 64 bit patches from dmd1, other fixes from Brad

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2010 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, StorageClass storage_class, Type *type)
35     : Declaration(id)
36 {
37     //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
38     //printf("storage_class = x%x\n", storage_class);
39     this->storage_class = storage_class;
40     this->type = type;
41     this->loc = loc;
42     this->endloc = endloc;
43     fthrows = NULL;
44     frequire = NULL;
45     fdrequire = NULL;
46     fdensure = NULL;
47     outId = NULL;
48     vresult = NULL;
49     returnLabel = NULL;
50     fensure = NULL;
51     fbody = NULL;
52     localsymtab = NULL;
53     vthis = NULL;
54     v_arguments = NULL;
55 #if IN_GCC
56     v_argptr = NULL;
57 #endif
58     v_argsave = NULL;
59     parameters = NULL;
60     labtab = NULL;
61     overnext = NULL;
62     vtblIndex = -1;
63     hasReturnExp = 0;
64     naked = 0;
65     inlineStatus = ILSuninitialized;
66     inlineNest = 0;
67     inlineAsm = 0;
68     cantInterpret = 0;
69     semanticRun = PASSinit;
70 #if DMDV1
71     nestedFrameRef = 0;
72 #endif
73     fes = NULL;
74     introducing = 0;
75     tintro = NULL;
76     /* The type given for "infer the return type" is a TypeFunction with
77      * NULL for the return type.
78      */
79     inferRetType = (type && type->nextOf() == NULL);
80     hasReturnExp = 0;
81     nrvo_can = 1;
82     nrvo_var = NULL;
83     shidden = NULL;
84 #if DMDV2
85     builtin = BUILTINunknown;
86     tookAddressOf = 0;
87 #endif
88 }
89
90 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
91 {
92     FuncDeclaration *f;
93
94     //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
95     if (s)
96         f = (FuncDeclaration *)s;
97     else
98         f = new FuncDeclaration(loc, endloc, ident, storage_class, type->syntaxCopy());
99     f->outId = outId;
100     f->frequire = frequire ? frequire->syntaxCopy() : NULL;
101     f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
102     f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
103     assert(!fthrows); // deprecated
104     return f;
105 }
106
107
108 // Do the semantic analysis on the external interface to the function.
109
110 void FuncDeclaration::semantic(Scope *sc)
111 {   TypeFunction *f;
112     AggregateDeclaration *ad;
113     StructDeclaration *sd;
114     ClassDeclaration *cd;
115     InterfaceDeclaration *id;
116     Dsymbol *pd;
117
118 #if 0
119     printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
120     if (isFuncLiteralDeclaration())
121         printf("\tFuncLiteralDeclaration()\n");
122     printf("sc->parent = %s, parent = %s\n", sc->parent->toChars(), parent ? parent->toChars() : "");
123     printf("type: %p, %s\n", type, type->toChars());
124 #endif
125
126     if (semanticRun != PASSinit && isFuncLiteralDeclaration())
127     {
128         /* Member functions that have return types that are
129          * forward references can have semantic() run more than
130          * once on them.
131          * See test\interface2.d, test20
132          */
133         return;
134     }
135
136     parent = sc->parent;
137     Dsymbol *parent = toParent();
138
139     if (semanticRun >= PASSsemanticdone)
140     {
141         if (!parent->isClassDeclaration())
142         {
143             return;
144         }
145         // need to re-run semantic() in order to set the class's vtbl[]
146     }
147     else
148     {
149         assert(semanticRun <= PASSsemantic);
150         semanticRun = PASSsemantic;
151     }
152
153     unsigned dprogress_save = Module::dprogress;
154
155     foverrides.setDim(0);       // reset in case semantic() is being retried for this function
156
157     storage_class |= sc->stc & ~STCref;
158     ad = isThis();
159     if (ad)
160         storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
161
162     //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
163
164     if (!originalType)
165         originalType = type;
166     if (!type->deco)
167     {
168         sc = sc->push();
169         sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCdisable
170             | STCsafe | STCtrusted | STCsystem);      // forward to function type
171
172         if (isCtorDeclaration())
173             sc->flags |= SCOPEctor;
174         type = type->semantic(loc, sc);
175         sc = sc->pop();
176
177         /* Apply const, immutable and shared storage class
178          * to the function type
179          */
180         StorageClass stc = storage_class;
181         if (type->isImmutable())
182             stc |= STCimmutable;
183         if (type->isConst())
184             stc |= STCconst;
185         if (type->isShared() || storage_class & STCsynchronized)
186             stc |= STCshared;
187         if (type->isWild())
188             stc |= STCwild;
189         switch (stc & STC_TYPECTOR)
190         {
191             case STCimmutable:
192             case STCimmutable | STCconst:
193             case STCimmutable | STCconst | STCshared:
194             case STCimmutable | STCshared:
195             case STCimmutable | STCwild:
196             case STCimmutable | STCconst | STCwild:
197             case STCimmutable | STCconst | STCshared | STCwild:
198             case STCimmutable | STCshared | STCwild:
199                 // Don't use toInvariant(), as that will do a merge()
200                 type = type->makeInvariant();
201                 goto Lmerge;
202
203             case STCconst:
204             case STCconst | STCwild:
205                 type = type->makeConst();
206                 goto Lmerge;
207
208             case STCshared | STCconst:
209             case STCshared | STCconst | STCwild:
210                 type = type->makeSharedConst();
211                 goto Lmerge;
212
213             case STCshared:
214                 type = type->makeShared();
215                 goto Lmerge;
216
217             case STCwild:
218                 type = type->makeWild();
219                 goto Lmerge;
220
221             case STCshared | STCwild:
222                 type = type->makeSharedWild();
223                 goto Lmerge;
224
225             Lmerge:
226                 if (!(type->ty == Tfunction && !type->nextOf()))
227                     /* Can't do merge if return type is not known yet
228                      */
229                     type->deco = type->merge()->deco;
230                 break;
231
232             case 0:
233                 break;
234
235             default:
236                 assert(0);
237         }
238     }
239     storage_class &= ~STCref;
240     if (type->ty != Tfunction)
241     {
242         error("%s must be a function instead of %s", toChars(), type->toChars());
243         return;
244     }
245     f = (TypeFunction *)(type);
246     size_t nparams = Parameter::dim(f->parameters);
247
248     linkage = sc->linkage;
249     protection = sc->protection;
250
251     if (storage_class & STCscope)
252         error("functions cannot be scope");
253
254     if (isAbstract() && !isVirtual())
255         error("non-virtual functions cannot be abstract");
256
257     if ((f->isConst() || f->isImmutable()) && !isThis())
258         error("without 'this' cannot be const/immutable");
259
260     if (isAbstract() && isFinal())
261         error("cannot be both final and abstract");
262 #if 0
263     if (isAbstract() && fbody)
264         error("abstract functions cannot have bodies");
265 #endif
266
267 #if 0
268     if (isStaticConstructor() || isStaticDestructor())
269     {
270         if (!isStatic() || type->nextOf()->ty != Tvoid)
271             error("static constructors / destructors must be static void");
272         if (f->arguments && f->arguments->dim)
273             error("static constructors / destructors must have empty parameter list");
274         // BUG: check for invalid storage classes
275     }
276 #endif
277
278 #ifdef IN_GCC
279     {
280         AggregateDeclaration *ad = parent->isAggregateDeclaration();
281         if (ad)
282             ad->methods.push(this);
283     }
284 #endif
285     sd = parent->isStructDeclaration();
286     if (sd)
287     {
288         if (isCtorDeclaration())
289         {
290             goto Ldone;
291         }
292 #if 0
293         // Verify no constructors, destructors, etc.
294         if (isCtorDeclaration()
295             //||isDtorDeclaration()
296             //|| isInvariantDeclaration()
297             //|| isUnitTestDeclaration()
298            )
299         {
300             error("special member functions not allowed for %ss", sd->kind());
301         }
302
303         if (!sd->inv)
304             sd->inv = isInvariantDeclaration();
305
306         if (!sd->aggNew)
307             sd->aggNew = isNewDeclaration();
308
309         if (isDelete())
310         {
311             if (sd->aggDelete)
312                 error("multiple delete's for struct %s", sd->toChars());
313             sd->aggDelete = (DeleteDeclaration *)(this);
314         }
315 #endif
316     }
317
318     id = parent->isInterfaceDeclaration();
319     if (id)
320     {
321         storage_class |= STCabstract;
322
323         if (isCtorDeclaration() ||
324 #if DMDV2
325             isPostBlitDeclaration() ||
326 #endif
327             isDtorDeclaration() ||
328             isInvariantDeclaration() ||
329             isUnitTestDeclaration() || isNewDeclaration() || isDelete())
330             error("constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface %s", id->toChars());
331         if (fbody && isVirtual())
332             error("function body is not abstract in interface %s", id->toChars());
333     }
334
335     /* Contracts can only appear without a body when they are virtual interface functions
336      */
337     if (!fbody && (fensure || frequire) && !(id && isVirtual()))
338         error("in and out contracts require function body");
339
340     /* Template member functions aren't virtual:
341      *   interface TestInterface { void tpl(T)(); }
342      * and so won't work in interfaces
343      */
344     if ((pd = toParent()) != NULL &&
345         pd->isTemplateInstance() &&
346         (pd = toParent2()) != NULL &&
347         (id = pd->isInterfaceDeclaration()) != NULL)
348     {
349         error("template member functions are not allowed in interface %s", id->toChars());
350     }
351
352     cd = parent->isClassDeclaration();
353     if (cd)
354     {   int vi;
355         CtorDeclaration *ctor;
356         DtorDeclaration *dtor;
357         InvariantDeclaration *inv;
358
359         if (isCtorDeclaration())
360         {
361 //          ctor = (CtorDeclaration *)this;
362 //          if (!cd->ctor)
363 //              cd->ctor = ctor;
364             return;
365         }
366
367 #if 0
368         dtor = isDtorDeclaration();
369         if (dtor)
370         {
371             if (cd->dtor)
372                 error("multiple destructors for class %s", cd->toChars());
373             cd->dtor = dtor;
374         }
375
376         inv = isInvariantDeclaration();
377         if (inv)
378         {
379             cd->inv = inv;
380         }
381
382         if (isNewDeclaration())
383         {
384             if (!cd->aggNew)
385                 cd->aggNew = (NewDeclaration *)(this);
386         }
387
388         if (isDelete())
389         {
390             if (cd->aggDelete)
391                 error("multiple delete's for class %s", cd->toChars());
392             cd->aggDelete = (DeleteDeclaration *)(this);
393         }
394 #endif
395
396         if (storage_class & STCabstract)
397             cd->isabstract = 1;
398
399         // if static function, do not put in vtbl[]
400         if (!isVirtual())
401         {
402             //printf("\tnot virtual\n");
403             goto Ldone;
404         }
405
406         /* Find index of existing function in base class's vtbl[] to override
407          * (the index will be the same as in cd's current vtbl[])
408          */
409         vi = cd->baseClass ? findVtblIndex(&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
410                            : -1;
411
412         switch (vi)
413         {
414             case -1:
415                 /* Didn't find one, so
416                  * This is an 'introducing' function which gets a new
417                  * slot in the vtbl[].
418                  */
419
420                 // Verify this doesn't override previous final function
421                 if (cd->baseClass)
422                 {   Dsymbol *s = cd->baseClass->search(loc, ident, 0);
423                     if (s)
424                     {
425                         FuncDeclaration *f = s->isFuncDeclaration();
426                         f = f->overloadExactMatch(type);
427                         if (f && f->isFinal() && f->prot() != PROTprivate)
428                             error("cannot override final function %s", f->toPrettyChars());
429                     }
430                 }
431
432                 if (isFinal())
433                 {
434                     if (isOverride())
435                         error("is marked as override, but does not override any function");
436                     cd->vtblFinal.push(this);
437                 }
438                 else
439                 {
440                     // Append to end of vtbl[]
441                     //printf("\tintroducing function\n");
442                     introducing = 1;
443                     vi = cd->vtbl.dim;
444                     cd->vtbl.push(this);
445                     vtblIndex = vi;
446                 }
447                 break;
448
449             case -2:    // can't determine because of fwd refs
450                 cd->sizeok = 2; // can't finish due to forward reference
451                 Module::dprogress = dprogress_save;
452                 return;
453
454             default:
455             {   FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.data[vi];
456                 // This function is covariant with fdv
457                 if (fdv->isFinal())
458                     error("cannot override final function %s", fdv->toPrettyChars());
459
460 #if DMDV2
461                 if (!isOverride())
462                     warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
463 #endif
464
465                 if (fdv->toParent() == parent)
466                 {
467                     // If both are mixins, then error.
468                     // If either is not, the one that is not overrides
469                     // the other.
470                     if (fdv->parent->isClassDeclaration())
471                         break;
472                     if (!this->parent->isClassDeclaration()
473 #if !BREAKABI
474                         && !isDtorDeclaration()
475 #endif
476 #if DMDV2
477                         && !isPostBlitDeclaration()
478 #endif
479                         )
480                         error("multiple overrides of same function");
481                 }
482                 cd->vtbl.data[vi] = (void *)this;
483                 vtblIndex = vi;
484
485                 /* Remember which functions this overrides
486                  */
487                 foverrides.push(fdv);
488
489                 /* This works by whenever this function is called,
490                  * it actually returns tintro, which gets dynamically
491                  * cast to type. But we know that tintro is a base
492                  * of type, so we could optimize it by not doing a
493                  * dynamic cast, but just subtracting the isBaseOf()
494                  * offset if the value is != null.
495                  */
496
497                 if (fdv->tintro)
498                     tintro = fdv->tintro;
499                 else if (!type->equals(fdv->type))
500                 {
501                     /* Only need to have a tintro if the vptr
502                      * offsets differ
503                      */
504                     int offset;
505                     if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
506                     {
507                         tintro = fdv->type;
508                     }
509                 }
510                 break;
511             }
512         }
513
514         /* Go through all the interface bases.
515          * If this function is covariant with any members of those interface
516          * functions, set the tintro.
517          */
518         for (int i = 0; i < cd->interfaces_dim; i++)
519         {
520             BaseClass *b = cd->interfaces[i];
521             vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
522             switch (vi)
523             {
524                 case -1:
525                     break;
526
527                 case -2:
528                     cd->sizeok = 2;     // can't finish due to forward reference
529                     Module::dprogress = dprogress_save;
530                     return;
531
532                 default:
533                 {   FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
534                     Type *ti = NULL;
535
536                     /* Remember which functions this overrides
537                      */
538                     foverrides.push(fdv);
539
540                     if (fdv->tintro)
541                         ti = fdv->tintro;
542                     else if (!type->equals(fdv->type))
543                     {
544                         /* Only need to have a tintro if the vptr
545                          * offsets differ
546                          */
547                         unsigned errors = global.errors;
548                         global.gag++;            // suppress printing of error messages
549                         int offset;
550                         int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset);
551                         global.gag--;            // suppress printing of error messages
552                         if (errors != global.errors)
553                         {
554                             // any error in isBaseOf() is a forward reference error, so we bail out
555                             global.errors = errors;
556                             cd->sizeok = 2;    // can't finish due to forward reference
557                             Module::dprogress = dprogress_save;
558                             return;
559                         }
560                         if (baseOf)
561                         {
562                             ti = fdv->type;
563                         }
564                     }
565                     if (ti)
566                     {
567                         if (tintro && !tintro->equals(ti))
568                         {
569                             error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
570                         }
571                         tintro = ti;
572                     }
573                     goto L2;
574                 }
575             }
576         }
577
578         if (introducing && isOverride())
579         {
580             error("does not override any function");
581         }
582
583     L2: ;
584
585         /* Go through all the interface bases.
586          * Disallow overriding any final functions in the interface(s).
587          */
588         for (int i = 0; i < cd->interfaces_dim; i++)
589         {
590             BaseClass *b = cd->interfaces[i];
591             if (b->base)
592             {
593                 Dsymbol *s = search_function(b->base, ident);
594                 if (s)
595                 {
596                     FuncDeclaration *f = s->isFuncDeclaration();
597                     if (f)
598                     {
599                         f = f->overloadExactMatch(type);
600                         if (f && f->isFinal() && f->prot() != PROTprivate)
601                             error("cannot override final function %s.%s", b->base->toChars(), f->toPrettyChars());
602                     }
603                 }
604             }
605         }
606     }
607     else if (isOverride() && !parent->isTemplateInstance())
608         error("override only applies to class member functions");
609
610     /* Do not allow template instances to add virtual functions
611      * to a class.
612      */
613     if (isVirtual())
614     {
615         TemplateInstance *ti = parent->isTemplateInstance();
616         if (ti)
617         {
618             // Take care of nested templates
619             while (1)
620             {
621                 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
622                 if (!ti2)
623                     break;
624                 ti = ti2;
625             }
626
627             // If it's a member template
628             ClassDeclaration *cd = ti->tempdecl->isClassMember();
629             if (cd)
630             {
631                 error("cannot use template to add virtual function to class '%s'", cd->toChars());
632             }
633         }
634     }
635
636     if (isMain())
637     {
638         // Check parameters to see if they are either () or (char[][] args)
639         switch (nparams)
640         {
641             case 0:
642                 break;
643
644             case 1:
645             {
646                 Parameter *arg0 = Parameter::getNth(f->parameters, 0);
647                 if (arg0->type->ty != Tarray ||
648                     arg0->type->nextOf()->ty != Tarray ||
649                     arg0->type->nextOf()->nextOf()->ty != Tchar ||
650                     arg0->storageClass & (STCout | STCref | STClazy))
651                     goto Lmainerr;
652                 break;
653             }
654
655             default:
656                 goto Lmainerr;
657         }
658
659         if (!f->nextOf())
660             error("must return int or void");
661         else if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
662             error("must return int or void, not %s", f->nextOf()->toChars());
663         if (f->varargs)
664         {
665         Lmainerr:
666             error("parameters must be main() or main(string[] args)");
667         }
668     }
669
670     if (ident == Id::assign && (sd || cd))
671     {   // Disallow identity assignment operator.
672
673         // opAssign(...)
674         if (nparams == 0)
675         {   if (f->varargs == 1)
676                 goto Lassignerr;
677         }
678         else
679         {
680             Parameter *arg0 = Parameter::getNth(f->parameters, 0);
681             Type *t0 = arg0->type->toBasetype();
682             Type *tb = sd ? sd->type : cd->type;
683             if (arg0->type->implicitConvTo(tb) ||
684                 (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
685                )
686             {
687                 if (nparams == 1)
688                     goto Lassignerr;
689                 Parameter *arg1 = Parameter::getNth(f->parameters, 1);
690                 if (arg1->defaultArg)
691                     goto Lassignerr;
692             }
693         }
694     }
695
696     if (isVirtual() && semanticRun != PASSsemanticdone)
697     {
698         /* Rewrite contracts as nested functions, then call them.
699          * Doing it as nested functions means that overriding functions
700          * can call them.
701          */
702         if (frequire)
703         {   /*   in { ... }
704              * becomes:
705              *   void __require() { ... }
706              *   __require();
707              */
708             Loc loc = frequire->loc;
709             TypeFunction *tf = new TypeFunction(NULL, Type::tvoid, 0, LINKd);
710             FuncDeclaration *fd = new FuncDeclaration(loc, loc,
711                 Id::require, STCundefined, tf);
712             fd->fbody = frequire;
713             Statement *s1 = new DeclarationStatement(loc, fd);
714             Expression *e = new CallExp(loc, new VarExp(loc, fd, 0), (Expressions *)NULL);
715             Statement *s2 = new ExpStatement(loc, e);
716             frequire = new CompoundStatement(loc, s1, s2);
717             fdrequire = fd;
718         }
719
720         if (!outId && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid)
721             outId = Id::result; // provide a default
722
723         if (fensure)
724         {   /*   out (result) { ... }
725              * becomes:
726              *   tret __ensure(ref tret result) { ... }
727              *   __ensure(result);
728              */
729             Loc loc = fensure->loc;
730             Parameters *arguments = new Parameters();
731             Parameter *a = NULL;
732             if (outId)
733             {   a = new Parameter(STCref | STCconst, f->nextOf(), outId, NULL);
734                 arguments->push(a);
735             }
736             TypeFunction *tf = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
737             FuncDeclaration *fd = new FuncDeclaration(loc, loc,
738                 Id::ensure, STCundefined, tf);
739             fd->fbody = fensure;
740             Statement *s1 = new DeclarationStatement(loc, fd);
741             Expression *eresult = NULL;
742             if (outId)
743                 eresult = new IdentifierExp(loc, outId);
744             Expression *e = new CallExp(loc, new VarExp(loc, fd, 0), eresult);
745             Statement *s2 = new ExpStatement(loc, e);
746             fensure = new CompoundStatement(loc, s1, s2);
747             fdensure = fd;
748         }
749     }
750
751 Ldone:
752     Module::dprogress++;
753     semanticRun = PASSsemanticdone;
754
755     /* Save scope for possible later use (if we need the
756      * function internals)
757      */
758     scope = new Scope(*sc);
759     scope->setNoFree();
760     return;
761
762 Lassignerr:
763     if (sd)
764     {
765         sd->hasIdentityAssign = 1;      // don't need to generate it
766         goto Ldone;
767     }
768     error("identity assignment operator overload is illegal");
769 }
770
771 void FuncDeclaration::semantic2(Scope *sc)
772 {
773 }
774
775 // Do the semantic analysis on the internals of the function.
776
777 void FuncDeclaration::semantic3(Scope *sc)
778 {   TypeFunction *f;
779     VarDeclaration *argptr = NULL;
780     VarDeclaration *_arguments = NULL;
781     int nerrors = global.errors;
782
783     if (!parent)
784     {
785         if (global.errors)
786             return;
787         //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
788         assert(0);
789     }
790     //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
791     //fflush(stdout);
792     //printf("storage class = x%x %x\n", sc->stc, storage_class);
793     //{ static int x; if (++x == 2) *(char*)0=0; }
794     //printf("\tlinkage = %d\n", sc->linkage);
795
796     //printf(" sc->incontract = %d\n", sc->incontract);
797     if (semanticRun >= PASSsemantic3)
798         return;
799     semanticRun = PASSsemantic3;
800
801     if (!type || type->ty != Tfunction)
802         return;
803     f = (TypeFunction *)(type);
804
805 #if 0
806     // Check the 'throws' clause
807     if (fthrows)
808     {
809         for (int i = 0; i < fthrows->dim; i++)
810         {
811             Type *t = (Type *)fthrows->data[i];
812
813             t = t->semantic(loc, sc);
814             if (!t->isClassHandle())
815                 error("can only throw classes, not %s", t->toChars());
816         }
817     }
818 #endif
819
820     frequire = mergeFrequire(frequire);
821     fensure = mergeFensure(fensure);
822
823     if (fbody || frequire || fensure)
824     {
825         /* Symbol table into which we place parameters and nested functions,
826          * solely to diagnose name collisions.
827          */
828         localsymtab = new DsymbolTable();
829
830         // Establish function scope
831         ScopeDsymbol *ss = new ScopeDsymbol();
832         ss->parent = sc->scopesym;
833         Scope *sc2 = sc->push(ss);
834         sc2->func = this;
835         sc2->parent = this;
836         sc2->callSuper = 0;
837         sc2->sbreak = NULL;
838         sc2->scontinue = NULL;
839         sc2->sw = NULL;
840         sc2->fes = fes;
841         sc2->linkage = LINKd;
842         sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated |
843                         STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref |
844                         STCproperty | STCsafe | STCtrusted | STCsystem);
845         sc2->protection = PROTpublic;
846         sc2->explicitProtection = 0;
847         sc2->structalign = 8;
848         sc2->incontract = 0;
849         sc2->tf = NULL;
850         sc2->noctor = 0;
851
852         // Declare 'this'
853         AggregateDeclaration *ad = isThis();
854         if (ad)
855         {   VarDeclaration *v;
856
857             if (isFuncLiteralDeclaration() && isNested() && !sc->intypeof)
858             {
859                 error("function literals cannot be class members");
860                 return;
861             }
862             else
863             {
864                 assert(!isNested() || sc->intypeof);    // can't be both member and nested
865                 assert(ad->handle);
866                 Type *thandle = ad->handle;
867 #if STRUCTTHISREF
868                 thandle = thandle->addMod(type->mod);
869                 thandle = thandle->addStorageClass(storage_class);
870                 //if (isPure())
871                     //thandle = thandle->addMod(MODconst);
872 #else
873                 if (storage_class & STCconst || type->isConst())
874                 {
875                     assert(0); // BUG: shared not handled
876                     if (thandle->ty == Tclass)
877                         thandle = thandle->constOf();
878                     else
879                     {   assert(thandle->ty == Tpointer);
880                         thandle = thandle->nextOf()->constOf()->pointerTo();
881                     }
882                 }
883                 else if (storage_class & STCimmutable || type->isImmutable())
884                 {
885                     if (thandle->ty == Tclass)
886                         thandle = thandle->invariantOf();
887                     else
888                     {   assert(thandle->ty == Tpointer);
889                         thandle = thandle->nextOf()->invariantOf()->pointerTo();
890                     }
891                 }
892                 else if (storage_class & STCshared || type->isShared())
893                 {
894                     assert(0);  // not implemented
895                 }
896 #endif
897                 v = new ThisDeclaration(loc, thandle);
898                 //v = new ThisDeclaration(loc, isCtorDeclaration() ? ad->handle : thandle);
899                 v->storage_class |= STCparameter;
900 #if STRUCTTHISREF
901                 if (thandle->ty == Tstruct)
902                     v->storage_class |= STCref;
903 #endif
904                 v->semantic(sc2);
905                 if (!sc2->insert(v))
906                     assert(0);
907                 v->parent = this;
908                 vthis = v;
909             }
910         }
911         else if (isNested())
912         {
913             /* The 'this' for a nested function is the link to the
914              * enclosing function's stack frame.
915              * Note that nested functions and member functions are disjoint.
916              */
917             VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo());
918             v->storage_class |= STCparameter;
919             v->semantic(sc2);
920             if (!sc2->insert(v))
921                 assert(0);
922             v->parent = this;
923             vthis = v;
924         }
925
926         // Declare hidden variable _arguments[] and _argptr
927         if (f->varargs == 1)
928         {
929 #if TARGET_NET
930             varArgs(sc2, f, argptr, _arguments);
931 #else
932             Type *t;
933
934             if (global.params.isX86_64)
935             {   // Declare save area for varargs registers
936                 Type *t = new TypeIdentifier(loc, Id::va_argsave_t);
937                 t = t->semantic(loc, sc);
938                 if (t == Type::terror)
939                     error("must import core.vararg to use variadic functions");
940                 else
941                 {
942                     v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
943                     v_argsave->semantic(sc2);
944                     sc2->insert(v_argsave);
945                     v_argsave->parent = this;
946                 }
947             }
948
949             if (f->linkage == LINKd)
950             {   // Declare _arguments[]
951 #if BREAKABI
952                 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
953                 v_arguments->storage_class = STCparameter;
954                 v_arguments->semantic(sc2);
955                 sc2->insert(v_arguments);
956                 v_arguments->parent = this;
957
958                 //t = Type::typeinfo->type->constOf()->arrayOf();
959                 t = Type::typeinfo->type->arrayOf();
960                 _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
961                 _arguments->semantic(sc2);
962                 sc2->insert(_arguments);
963                 _arguments->parent = this;
964 #else
965                 t = Type::typeinfo->type->arrayOf();
966                 v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
967                 v_arguments->storage_class = STCparameter | STCin;
968                 v_arguments->semantic(sc2);
969                 sc2->insert(v_arguments);
970                 v_arguments->parent = this;
971 #endif
972             }
973             if (f->linkage == LINKd || (parameters && parameters->dim))
974             {   // Declare _argptr
975 #if IN_GCC
976                 t = d_gcc_builtin_va_list_d_type;
977 #else
978                 t = Type::tvoid->pointerTo();
979 #endif
980                 argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
981                 argptr->semantic(sc2);
982                 sc2->insert(argptr);
983                 argptr->parent = this;
984             }
985 #endif
986         }
987
988 #if 0
989         // Propagate storage class from tuple parameters to their element-parameters.
990         if (f->parameters)
991         {
992             for (size_t i = 0; i < f->parameters->dim; i++)
993             {   Parameter *arg = (Parameter *)f->parameters->data[i];
994
995                 //printf("[%d] arg->type->ty = %d %s\n", i, arg->type->ty, arg->type->toChars());
996                 if (arg->type->ty == Ttuple)
997                 {   TypeTuple *t = (TypeTuple *)arg->type;
998                     size_t dim = Parameter::dim(t->arguments);
999                     for (size_t j = 0; j < dim; j++)
1000                     {   Parameter *narg = Parameter::getNth(t->arguments, j);
1001                         narg->storageClass = arg->storageClass;
1002                     }
1003                 }
1004             }
1005         }
1006 #endif
1007
1008         /* Declare all the function parameters as variables
1009          * and install them in parameters[]
1010          */
1011         size_t nparams = Parameter::dim(f->parameters);
1012         if (nparams)
1013         {   /* parameters[] has all the tuples removed, as the back end
1014              * doesn't know about tuples
1015              */
1016             parameters = new Dsymbols();
1017             parameters->reserve(nparams);
1018             for (size_t i = 0; i < nparams; i++)
1019             {
1020                 Parameter *arg = Parameter::getNth(f->parameters, i);
1021                 Identifier *id = arg->ident;
1022                 if (!id)
1023                 {
1024                     /* Generate identifier for un-named parameter,
1025                      * because we need it later on.
1026                      */
1027                     arg->ident = id = Identifier::generateId("_param_", i);
1028                 }
1029                 Type *vtype = arg->type;
1030                 //if (isPure())
1031                     //vtype = vtype->addMod(MODconst);
1032                 VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
1033                 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
1034                 v->storage_class |= STCparameter;
1035                 if (f->varargs == 2 && i + 1 == nparams)
1036                     v->storage_class |= STCvariadic;
1037                 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
1038                 v->semantic(sc2);
1039                 if (!sc2->insert(v))
1040                     error("parameter %s.%s is already defined", toChars(), v->toChars());
1041                 else
1042                     parameters->push(v);
1043                 localsymtab->insert(v);
1044                 v->parent = this;
1045             }
1046         }
1047
1048         // Declare the tuple symbols and put them in the symbol table,
1049         // but not in parameters[].
1050         if (f->parameters)
1051         {
1052             for (size_t i = 0; i < f->parameters->dim; i++)
1053             {   Parameter *arg = (Parameter *)f->parameters->data[i];
1054
1055                 if (!arg->ident)
1056                     continue;                   // never used, so ignore
1057                 if (arg->type->ty == Ttuple)
1058                 {   TypeTuple *t = (TypeTuple *)arg->type;
1059                     size_t dim = Parameter::dim(t->arguments);
1060                     Objects *exps = new Objects();
1061                     exps->setDim(dim);
1062                     for (size_t j = 0; j < dim; j++)
1063                     {   Parameter *narg = Parameter::getNth(t->arguments, j);
1064                         assert(narg->ident);
1065                         VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
1066                         assert(v);
1067                         Expression *e = new VarExp(v->loc, v);
1068                         exps->data[j] = (void *)e;
1069                     }
1070                     assert(arg->ident);
1071                     TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
1072                     //printf("declaring tuple %s\n", v->toChars());
1073                     v->isexp = 1;
1074                     if (!sc2->insert(v))
1075                         error("parameter %s.%s is already defined", toChars(), v->toChars());
1076                     localsymtab->insert(v);
1077                     v->parent = this;
1078                 }
1079             }
1080         }
1081
1082         /* Do the semantic analysis on the [in] preconditions and
1083          * [out] postconditions.
1084          */
1085         sc2->incontract++;
1086
1087         if (frequire)
1088         {   /* frequire is composed of the [in] contracts
1089              */
1090             // BUG: need to error if accessing out parameters
1091             // BUG: need to treat parameters as const
1092             // BUG: need to disallow returns and throws
1093             // BUG: verify that all in and ref parameters are read
1094             frequire = frequire->semantic(sc2);
1095             labtab = NULL;              // so body can't refer to labels
1096         }
1097
1098         if (fensure || addPostInvariant())
1099         {   /* fensure is composed of the [out] contracts
1100              */
1101             if (!type->nextOf())                // if return type is inferred
1102             {   /* This case:
1103                  *   auto fp = function() out { } body { };
1104                  * Can fix by doing semantic() onf fbody first.
1105                  */
1106                 error("post conditions are not supported if the return type is inferred");
1107                 return;
1108             }
1109
1110             ScopeDsymbol *sym = new ScopeDsymbol();
1111             sym->parent = sc2->scopesym;
1112             sc2 = sc2->push(sym);
1113
1114             assert(type->nextOf());
1115             if (type->nextOf()->ty == Tvoid)
1116             {
1117                 if (outId)
1118                     error("void functions have no result");
1119             }
1120             else
1121             {
1122                 if (!outId)
1123                     outId = Id::result;         // provide a default
1124             }
1125
1126             if (outId)
1127             {   // Declare result variable
1128                 Loc loc = this->loc;
1129
1130                 if (fensure)
1131                     loc = fensure->loc;
1132
1133                 VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
1134                 v->noscope = 1;
1135                 v->storage_class |= STCresult;
1136 #if DMDV2
1137                 if (!isVirtual())
1138                     v->storage_class |= STCconst;
1139                 if (f->isref)
1140                 {
1141                     v->storage_class |= STCref | STCforeach;
1142                 }
1143 #endif
1144                 sc2->incontract--;
1145                 v->semantic(sc2);
1146                 sc2->incontract++;
1147                 if (!sc2->insert(v))
1148                     error("out result %s is already defined", v->toChars());
1149                 v->parent = this;
1150                 vresult = v;
1151
1152                 // vresult gets initialized with the function return value
1153                 // in ReturnStatement::semantic()
1154             }
1155
1156             // BUG: need to treat parameters as const
1157             // BUG: need to disallow returns and throws
1158             if (fensure)
1159             {   fensure = fensure->semantic(sc2);
1160                 labtab = NULL;          // so body can't refer to labels
1161             }
1162
1163             if (!global.params.useOut)
1164             {   fensure = NULL;         // discard
1165                 vresult = NULL;
1166             }
1167
1168             // Postcondition invariant
1169             if (addPostInvariant())
1170             {
1171                 Expression *e = NULL;
1172                 if (isCtorDeclaration())
1173                 {
1174                     // Call invariant directly only if it exists
1175                     InvariantDeclaration *inv = ad->inv;
1176                     ClassDeclaration *cd = ad->isClassDeclaration();
1177
1178                     while (!inv && cd)
1179                     {
1180                         cd = cd->baseClass;
1181                         if (!cd)
1182                             break;
1183                         inv = cd->inv;
1184                     }
1185                     if (inv)
1186                     {
1187                         e = new DsymbolExp(0, inv);
1188                         e = new CallExp(0, e);
1189                         e = e->semantic(sc2);
1190                     }
1191                 }
1192                 else
1193                 {   // Call invariant virtually
1194                     Expression *v = new ThisExp(0);
1195                     v->type = vthis->type;
1196 #if STRUCTTHISREF
1197                     if (ad->isStructDeclaration())
1198                         v = v->addressOf(sc);
1199 #endif
1200                     e = new AssertExp(0, v);
1201                 }
1202                 if (e)
1203                 {
1204                     ExpStatement *s = new ExpStatement(0, e);
1205                     if (fensure)
1206                         fensure = new CompoundStatement(0, s, fensure);
1207                     else
1208                         fensure = s;
1209                 }
1210             }
1211
1212             if (fensure)
1213             {   returnLabel = new LabelDsymbol(Id::returnLabel);
1214                 LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
1215                 returnLabel->statement = ls;
1216             }
1217             sc2 = sc2->pop();
1218         }
1219
1220         sc2->incontract--;
1221
1222         if (fbody)
1223         {   ClassDeclaration *cd = isClassMember();
1224
1225             /* If this is a class constructor
1226              */
1227             if (isCtorDeclaration() && cd)
1228             {
1229                 for (int i = 0; i < cd->fields.dim; i++)
1230                 {   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
1231
1232                     v->ctorinit = 0;
1233                 }
1234             }
1235
1236             if (inferRetType || f->retStyle() != RETstack)
1237                 nrvo_can = 0;
1238
1239             fbody = fbody->semantic(sc2);
1240             if (!fbody)
1241                 fbody = new CompoundStatement(0, new Statements());
1242
1243             if (inferRetType)
1244             {   // If no return type inferred yet, then infer a void
1245                 if (!type->nextOf())
1246                 {
1247                     ((TypeFunction *)type)->next = Type::tvoid;
1248                     type = type->semantic(loc, sc);
1249                 }
1250                 f = (TypeFunction *)type;
1251             }
1252
1253             if (isStaticCtorDeclaration())
1254             {   /* It's a static constructor. Ensure that all
1255                  * ctor consts were initialized.
1256                  */
1257
1258                 Dsymbol *p = toParent();
1259                 ScopeDsymbol *ad = p->isScopeDsymbol();
1260                 if (!ad)
1261                 {
1262                     error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
1263                 }
1264                 else
1265                 {
1266                     for (int i = 0; i < ad->members->dim; i++)
1267                     {   Dsymbol *s = (Dsymbol *)ad->members->data[i];
1268
1269                         s->checkCtorConstInit();
1270                     }
1271                 }
1272             }
1273
1274             if (isCtorDeclaration() && cd)
1275             {
1276                 //printf("callSuper = x%x\n", sc2->callSuper);
1277
1278                 // Verify that all the ctorinit fields got initialized
1279                 if (!(sc2->callSuper & CSXthis_ctor))
1280                 {
1281                     for (int i = 0; i < cd->fields.dim; i++)
1282                     {   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
1283
1284                         if (v->ctorinit == 0 && v->isCtorinit() && !v->type->isMutable())
1285                             error("missing initializer for final field %s", v->toChars());
1286                     }
1287                 }
1288
1289                 if (!(sc2->callSuper & CSXany_ctor) &&
1290                     cd->baseClass && cd->baseClass->ctor)
1291                 {
1292                     sc2->callSuper = 0;
1293
1294                     // Insert implicit super() at start of fbody
1295                     Expression *e1 = new SuperExp(0);
1296                     Expression *e = new CallExp(0, e1);
1297
1298                     e = e->trySemantic(sc2);
1299                     if (!e)
1300                         error("no match for implicit super() call in constructor");
1301                     else
1302                     {
1303                         Statement *s = new ExpStatement(0, e);
1304                         fbody = new CompoundStatement(0, s, fbody);
1305                     }
1306                 }
1307             }
1308             else if (fes)
1309             {   // For foreach(){} body, append a return 0;
1310                 Expression *e = new IntegerExp(0);
1311                 Statement *s = new ReturnStatement(0, e);
1312                 fbody = new CompoundStatement(0, fbody, s);
1313                 assert(!returnLabel);
1314             }
1315             else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1316                 error("has no return statement, but is expected to return a value of type %s", type->nextOf()->toChars());
1317             else if (!inlineAsm)
1318             {
1319 #if DMDV2
1320                 // Check for errors related to 'nothrow'.
1321                 int nothrowErrors = global.errors;
1322                 int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru;
1323                 if (f->isnothrow && (global.errors != nothrowErrors) )
1324                     error("'%s' is nothrow yet may throw", toChars());
1325
1326                 int offend = blockexit & BEfallthru;
1327 #endif
1328                 if (type->nextOf()->ty == Tvoid)
1329                 {
1330                     if (offend && isMain())
1331                     {   // Add a return 0; statement
1332                         Statement *s = new ReturnStatement(0, new IntegerExp(0));
1333                         fbody = new CompoundStatement(0, fbody, s);
1334                     }
1335                 }
1336                 else
1337                 {
1338                     if (offend)
1339                     {   Expression *e;
1340 #if DMDV1
1341                         warning(loc, "no return exp; or assert(0); at end of function");
1342 #else
1343                         error("no return exp; or assert(0); at end of function");
1344 #endif
1345                         if (global.params.useAssert &&
1346                             !global.params.useInline)
1347                         {   /* Add an assert(0, msg); where the missing return
1348                              * should be.
1349                              */
1350                             e = new AssertExp(
1351                                   endloc,
1352                                   new IntegerExp(0),
1353                                   new StringExp(loc, (char *)"missing return expression")
1354                                 );
1355                         }
1356                         else
1357                             e = new HaltExp(endloc);
1358                         e = new CommaExp(0, e, type->nextOf()->defaultInit());
1359                         e = e->semantic(sc2);
1360                         Statement *s = new ExpStatement(0, e);
1361                         fbody = new CompoundStatement(0, fbody, s);
1362                     }
1363                 }
1364             }
1365         }
1366
1367         {
1368             Statements *a = new Statements();
1369
1370             // Merge in initialization of 'out' parameters
1371             if (parameters)
1372             {   for (size_t i = 0; i < parameters->dim; i++)
1373                 {
1374                     VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1375                     if (v->storage_class & STCout)
1376                     {
1377                         assert(v->init);
1378                         ExpInitializer *ie = v->init->isExpInitializer();
1379                         assert(ie);
1380                         if (ie->exp->op == TOKconstruct)
1381                             ie->exp->op = TOKassign; // construction occured in parameter processing
1382                         a->push(new ExpStatement(0, ie->exp));
1383                     }
1384                 }
1385             }
1386
1387             if (argptr)
1388             {   // Initialize _argptr
1389 #if IN_GCC
1390                 // Handled in FuncDeclaration::toObjFile
1391                 v_argptr = argptr;
1392                 v_argptr->init = new VoidInitializer(loc);
1393 #else
1394                 Type *t = argptr->type;
1395                 if (global.params.isX86_64)
1396                 {   // Initialize _argptr to point to v_argsave
1397                     Expression *e1 = new VarExp(0, argptr);
1398                     Expression *e = new SymOffExp(0, v_argsave, 6*8 + 8*16);
1399                     e->type = argptr->type;
1400                     e = new AssignExp(0, e1, e);
1401                     e = e->semantic(sc);
1402                     a->push(new ExpStatement(0, e));
1403                 }
1404                 else
1405                 {   // Initialize _argptr to point past non-variadic arg
1406                     VarDeclaration *p;
1407                     unsigned offset = 0;
1408
1409                     Expression *e1 = new VarExp(0, argptr);
1410                     // Find the last non-ref parameter
1411                     if (parameters && parameters->dim)
1412                     {
1413                         int lastNonref = parameters->dim -1;
1414                         p = (VarDeclaration *)parameters->data[lastNonref];
1415                         /* The trouble with out and ref parameters is that taking
1416                          * the address of it doesn't work, because later processing
1417                          * adds in an extra level of indirection. So we skip over them.
1418                          */
1419                         while (p->storage_class & (STCout | STCref))
1420                         {
1421                             --lastNonref;
1422                             offset += PTRSIZE;
1423                             if (lastNonref < 0)
1424                             {
1425                                 p = v_arguments;
1426                                 break;
1427                             }
1428                             p = (VarDeclaration *)parameters->data[lastNonref];
1429                         }
1430                     }
1431                     else
1432                         p = v_arguments;            // last parameter is _arguments[]
1433                     if (p->storage_class & STClazy)
1434                         // If the last parameter is lazy, it's the size of a delegate
1435                         offset += PTRSIZE * 2;
1436                     else
1437                         offset += p->type->size();
1438                     offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);  // assume stack aligns on pointer size
1439                     Expression *e = new SymOffExp(0, p, offset);
1440                     e->type = Type::tvoidptr;
1441                     //e = e->semantic(sc);
1442                     e = new AssignExp(0, e1, e);
1443                     e->type = t;
1444                     a->push(new ExpStatement(0, e));
1445                     p->isargptr = TRUE;
1446                 }
1447 #endif
1448             }
1449
1450             if (_arguments)
1451             {
1452                 /* Advance to elements[] member of TypeInfo_Tuple with:
1453                  *  _arguments = v_arguments.elements;
1454                  */
1455                 Expression *e = new VarExp(0, v_arguments);
1456                 e = new DotIdExp(0, e, Id::elements);
1457                 Expression *e1 = new VarExp(0, _arguments);
1458                 e = new ConstructExp(0, e1, e);
1459                 e = e->semantic(sc2);
1460                 a->push(new ExpStatement(0, e));
1461             }
1462
1463             // Merge contracts together with body into one compound statement
1464
1465 #ifdef _DH
1466             if (frequire && global.params.useIn)
1467             {   frequire->incontract = 1;
1468                 a->push(frequire);
1469             }
1470 #else
1471             if (frequire && global.params.useIn)
1472                 a->push(frequire);
1473 #endif
1474
1475             // Precondition invariant
1476             if (addPreInvariant())
1477             {
1478                 Expression *e = NULL;
1479                 if (isDtorDeclaration())
1480                 {
1481                     // Call invariant directly only if it exists
1482                     InvariantDeclaration *inv = ad->inv;
1483                     ClassDeclaration *cd = ad->isClassDeclaration();
1484
1485                     while (!inv && cd)
1486                     {
1487                         cd = cd->baseClass;
1488                         if (!cd)
1489                             break;
1490                         inv = cd->inv;
1491                     }
1492                     if (inv)
1493                     {
1494                         e = new DsymbolExp(0, inv);
1495                         e = new CallExp(0, e);
1496                         e = e->semantic(sc2);
1497                     }
1498                 }
1499                 else
1500                 {   // Call invariant virtually
1501                     Expression *v = new ThisExp(0);
1502                     v->type = vthis->type;
1503 #if STRUCTTHISREF
1504                     if (ad->isStructDeclaration())
1505                         v = v->addressOf(sc);
1506 #endif
1507                     Expression *se = new StringExp(0, (char *)"null this");
1508                     se = se->semantic(sc);
1509                     se->type = Type::tchar->arrayOf();
1510                     e = new AssertExp(loc, v, se);
1511                 }
1512                 if (e)
1513                 {
1514                     ExpStatement *s = new ExpStatement(0, e);
1515                     a->push(s);
1516                 }
1517             }
1518
1519             if (fbody)
1520                 a->push(fbody);
1521
1522             if (fensure)
1523             {
1524                 a->push(returnLabel->statement);
1525
1526                 if (type->nextOf()->ty != Tvoid)
1527                 {
1528                     // Create: return vresult;
1529                     assert(vresult);
1530                     Expression *e = new VarExp(0, vresult);
1531                     if (tintro)
1532                     {   e = e->implicitCastTo(sc, tintro->nextOf());
1533                         e = e->semantic(sc);
1534                     }
1535                     ReturnStatement *s = new ReturnStatement(0, e);
1536                     a->push(s);
1537                 }
1538             }
1539
1540             fbody = new CompoundStatement(0, a);
1541 #if DMDV2
1542             /* Append destructor calls for parameters as finally blocks.
1543              */
1544             if (parameters)
1545             {   for (size_t i = 0; i < parameters->dim; i++)
1546                 {
1547                     VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1548
1549                     if (v->storage_class & (STCref | STCout))
1550                         continue;
1551
1552                     /* Don't do this for static arrays, since static
1553                      * arrays are called by reference. Remove this
1554                      * when we change them to call by value.
1555                      */
1556                     if (v->type->toBasetype()->ty == Tsarray)
1557                         continue;
1558
1559                     Expression *e = v->callScopeDtor(sc2);
1560                     if (e)
1561                     {   Statement *s = new ExpStatement(0, e);
1562                         s = s->semantic(sc2);
1563                         if (fbody->blockExit(f->isnothrow) == BEfallthru)
1564                             fbody = new CompoundStatement(0, fbody, s);
1565                         else
1566                             fbody = new TryFinallyStatement(0, fbody, s);
1567                     }
1568                 }
1569             }
1570 #endif
1571
1572 #if 1
1573             if (isSynchronized())
1574             {   /* Wrap the entire function body in a synchronized statement
1575                  */
1576                 ClassDeclaration *cd = parent->isClassDeclaration();
1577                 if (cd)
1578                 {
1579 #if TARGET_WINDOS
1580                     if (/*config.flags2 & CFG2seh &&*/  // always on for WINDOS
1581                         !isStatic() && !fbody->usesEH())
1582                     {
1583                         /* The back end uses the "jmonitor" hack for syncing;
1584                          * no need to do the sync at this level.
1585                          */
1586                     }
1587                     else
1588 #endif
1589                     {
1590                         Expression *vsync;
1591                         if (isStatic())
1592                         {   // The monitor is in the ClassInfo
1593                             vsync = new DotIdExp(loc, new DsymbolExp(loc, cd), Id::classinfo);
1594                         }
1595                         else
1596                         {   // 'this' is the monitor
1597                             vsync = new VarExp(loc, vthis);
1598                         }
1599                         fbody = new PeelStatement(fbody);       // don't redo semantic()
1600                         fbody = new SynchronizedStatement(loc, vsync, fbody);
1601                         fbody = fbody->semantic(sc2);
1602                     }
1603                 }
1604                 else
1605                 {
1606                     error("synchronized function %s must be a member of a class", toChars());
1607                 }
1608             }
1609 #endif
1610         }
1611
1612         sc2->callSuper = 0;
1613         sc2->pop();
1614     }
1615
1616     if (global.gag && global.errors != nerrors)
1617         semanticRun = PASSsemanticdone; // Ensure errors get reported again
1618     else
1619         semanticRun = PASSsemantic3done;
1620     //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
1621     //fflush(stdout);
1622 }
1623
1624 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1625 {
1626     //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1627
1628     StorageClassDeclaration::stcToCBuffer(buf, storage_class);
1629     type->toCBuffer(buf, ident, hgs);
1630     bodyToCBuffer(buf, hgs);
1631 }
1632
1633 int FuncDeclaration::equals(Object *o)
1634 {
1635     if (this == o)
1636         return TRUE;
1637
1638     Dsymbol *s = isDsymbol(o);
1639     if (s)
1640     {
1641         FuncDeclaration *fd = s->isFuncDeclaration();
1642         if (fd)
1643         {
1644             return toParent()->equals(fd->toParent()) &&
1645                 ident->equals(fd->ident) && type->equals(fd->type);
1646         }
1647     }
1648     return FALSE;
1649 }
1650
1651 void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1652 {
1653     if (fbody &&
1654         (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1655        )
1656     {   buf->writenl();
1657
1658         // in{}
1659         if (frequire)
1660         {   buf->writestring("in");
1661             buf->writenl();
1662             frequire->toCBuffer(buf, hgs);
1663         }
1664
1665         // out{}
1666         if (fensure)
1667         {   buf->writestring("out");
1668             if (outId)
1669             {   buf->writebyte('(');
1670                 buf->writestring(outId->toChars());
1671                 buf->writebyte(')');
1672             }
1673             buf->writenl();
1674             fensure->toCBuffer(buf, hgs);
1675         }
1676
1677         if (frequire || fensure)
1678         {   buf->writestring("body");
1679             buf->writenl();
1680         }
1681
1682         buf->writebyte('{');
1683         buf->writenl();
1684         fbody->toCBuffer(buf, hgs);
1685         buf->writebyte('}');
1686         buf->writenl();
1687     }
1688     else
1689     {   buf->writeByte(';');
1690         buf->writenl();
1691     }
1692 }
1693
1694 /****************************************************
1695  * Merge into this function the 'in' contracts of all it overrides.
1696  * 'in's are OR'd together, i.e. only one of them needs to pass.
1697  */
1698
1699 Statement *FuncDeclaration::mergeFrequire(Statement *sf)
1700 {
1701     /* Implementing this is done by having the overriding function call
1702      * nested functions (the fdrequire functions) nested inside the overridden
1703      * function. This requires that the stack layout of the calling function's
1704      * parameters and 'this' pointer be in the same place (as the nested
1705      * function refers to them).
1706      * This is easy for the parameters, as they are all on the stack in the same
1707      * place by definition, since it's an overriding function. The problem is
1708      * getting the 'this' pointer in the same place, since it is a local variable.
1709      * We did some hacks in the code generator to make this happen:
1710      *  1. always generate exception handler frame, or at least leave space for it
1711      *     in the frame (Windows 32 SEH only)
1712      *  2. always generate an EBP style frame
1713      *  3. since 'this' is passed in a register that is subsequently copied into
1714      *     a stack local, allocate that local immediately following the exception
1715      *     handler block, so it is always at the same offset from EBP.
1716      */
1717     for (int i = 0; i < foverrides.dim; i++)
1718     {
1719         FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
1720
1721         /* The semantic pass on the contracts of the overridden functions must
1722          * be completed before code generation occurs (bug 3602).
1723          */
1724         if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done)
1725         {
1726             assert(fdv->scope);
1727             Scope *sc = fdv->scope->push();
1728             sc->stc &= ~STCoverride;
1729             fdv->semantic3(sc);
1730             sc->pop();
1731         }
1732
1733         sf = fdv->mergeFrequire(sf);
1734         if (fdv->fdrequire)
1735         {
1736             //printf("fdv->frequire: %s\n", fdv->frequire->toChars());
1737             /* Make the call:
1738              *   try { __require(); }
1739              *   catch { frequire; }
1740              */
1741             Expression *eresult = NULL;
1742             Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire, 0), eresult);
1743             Statement *s2 = new ExpStatement(loc, e);
1744
1745             if (sf)
1746             {   Catch *c = new Catch(loc, NULL, NULL, sf);
1747                 Array *catches = new Array();
1748                 catches->push(c);
1749                 sf = new TryCatchStatement(loc, s2, catches);
1750             }
1751             else
1752                 sf = s2;
1753         }
1754     }
1755     return sf;
1756 }
1757
1758 /****************************************************
1759  * Merge into this function the 'out' contracts of all it overrides.
1760  * 'out's are AND'd together, i.e. all of them need to pass.
1761  */
1762
1763 Statement *FuncDeclaration::mergeFensure(Statement *sf)
1764 {
1765     /* Same comments as for mergeFrequire(), except that we take care
1766      * of generating a consistent reference to the 'result' local by
1767      * explicitly passing 'result' to the nested function as a reference
1768      * argument.
1769      * This won't work for the 'this' parameter as it would require changing
1770      * the semantic code for the nested function so that it looks on the parameter
1771      * list for the 'this' pointer, something that would need an unknown amount
1772      * of tweaking of various parts of the compiler that I'd rather leave alone.
1773      */
1774     for (int i = 0; i < foverrides.dim; i++)
1775     {
1776         FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
1777
1778         /* The semantic pass on the contracts of the overridden functions must
1779          * be completed before code generation occurs (bug 3602 and 5230).
1780          */
1781         if (fdv->fdensure && fdv->fdensure->semanticRun != PASSsemantic3done)
1782         {
1783             assert(fdv->scope);
1784             Scope *sc = fdv->scope->push();
1785             sc->stc &= ~STCoverride;
1786             fdv->semantic3(sc);
1787             sc->pop();
1788         }
1789
1790         sf = fdv->mergeFensure(sf);
1791         if (fdv->fdensure)
1792         {
1793             //printf("fdv->fensure: %s\n", fdv->fensure->toChars());
1794             // Make the call: __ensure(result)
1795             Expression *eresult = NULL;
1796             if (outId)
1797                 eresult = new IdentifierExp(loc, outId);
1798             Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure, 0), eresult);
1799             Statement *s2 = new ExpStatement(loc, e);
1800
1801             if (sf)
1802             {
1803                 sf = new CompoundStatement(fensure->loc, s2, sf);
1804             }
1805             else
1806                 sf = s2;
1807         }
1808     }
1809     return sf;
1810 }
1811
1812 /****************************************************
1813  * Determine if 'this' overrides fd.
1814  * Return !=0 if it does.
1815  */
1816
1817 int FuncDeclaration::overrides(FuncDeclaration *fd)
1818 {   int result = 0;
1819
1820     if (fd->ident == ident)
1821     {
1822         int cov = type->covariant(fd->type);
1823         if (cov)
1824         {   ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1825             ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1826
1827             if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1828                 result = 1;
1829         }
1830     }
1831     return result;
1832 }
1833
1834 /*************************************************
1835  * Find index of function in vtbl[0..dim] that
1836  * this function overrides.
1837  * Prefer an exact match to a covariant one.
1838  * Returns:
1839  *      -1      didn't find one
1840  *      -2      can't determine because of forward references
1841  */
1842
1843 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
1844 {
1845     FuncDeclaration *mismatch = NULL;
1846     int bestvi = -1;
1847     for (int vi = 0; vi < dim; vi++)
1848     {
1849         FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
1850         if (fdv && fdv->ident == ident)
1851         {
1852             if (type->equals(fdv->type))        // if exact match
1853                 return vi;                      // no need to look further
1854
1855             int cov = type->covariant(fdv->type);
1856             //printf("\tbaseclass cov = %d\n", cov);
1857             switch (cov)
1858             {
1859                 case 0:         // types are distinct
1860                     break;
1861
1862                 case 1:
1863                     bestvi = vi;        // covariant, but not identical
1864                     break;              // keep looking for an exact match
1865
1866                 case 2:
1867                     mismatch = fdv;     // overrides, but is not covariant
1868                     break;              // keep looking for an exact match
1869
1870                 case 3:
1871                     return -2;  // forward references
1872
1873                 default:
1874                     assert(0);
1875             }
1876         }
1877     }
1878     if (bestvi == -1 && mismatch)
1879     {
1880         //type->print();
1881         //mismatch->type->print();
1882         //printf("%s %s\n", type->deco, mismatch->type->deco);
1883         error("of type %s overrides but is not covariant with %s of type %s",
1884             type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
1885     }
1886     return bestvi;
1887 }
1888
1889 /****************************************************
1890  * Overload this FuncDeclaration with the new one f.
1891  * Return !=0 if successful; i.e. no conflict.
1892  */
1893
1894 int FuncDeclaration::overloadInsert(Dsymbol *s)
1895 {
1896     FuncDeclaration *f;
1897     AliasDeclaration *a;
1898
1899     //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
1900     a = s->isAliasDeclaration();
1901     if (a)
1902     {
1903         if (overnext)
1904             return overnext->overloadInsert(a);
1905         if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1906         {
1907             //printf("\ta = '%s'\n", a->type->toChars());
1908             return FALSE;
1909         }
1910         overnext = a;
1911         //printf("\ttrue: no conflict\n");
1912         return TRUE;
1913     }
1914     f = s->isFuncDeclaration();
1915     if (!f)
1916         return FALSE;
1917
1918 #if 0
1919     /* Disable this check because:
1920      *  const void foo();
1921      * semantic() isn't run yet on foo(), so the const hasn't been
1922      * applied yet.
1923      */
1924     if (type)
1925     {   printf("type = %s\n", type->toChars());
1926         printf("f->type = %s\n", f->type->toChars());
1927     }
1928     if (type && f->type &&      // can be NULL for overloaded constructors
1929         f->type->covariant(type) &&
1930         f->type->mod == type->mod &&
1931         !isFuncAliasDeclaration())
1932     {
1933         //printf("\tfalse: conflict %s\n", kind());
1934         return FALSE;
1935     }
1936 #endif
1937
1938     if (overnext)
1939         return overnext->overloadInsert(f);
1940     overnext = f;
1941     //printf("\ttrue: no conflict\n");
1942     return TRUE;
1943 }
1944
1945 /********************************************
1946  * Find function in overload list that exactly matches t.
1947  */
1948
1949 /***************************************************
1950  * Visit each overloaded function in turn, and call
1951  * (*fp)(param, f) on it.
1952  * Exit when no more, or (*fp)(param, f) returns 1.
1953  * Returns:
1954  *      0       continue
1955  *      1       done
1956  */
1957
1958 int overloadApply(FuncDeclaration *fstart,
1959         int (*fp)(void *, FuncDeclaration *),
1960         void *param)
1961 {
1962     FuncDeclaration *f;
1963     Declaration *d;
1964     Declaration *next;
1965
1966     for (d = fstart; d; d = next)
1967     {   FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1968
1969         if (fa)
1970         {
1971             if (overloadApply(fa->funcalias, fp, param))
1972                 return 1;
1973             next = fa->overnext;
1974         }
1975         else
1976         {
1977             AliasDeclaration *a = d->isAliasDeclaration();
1978
1979             if (a)
1980             {
1981                 Dsymbol *s = a->toAlias();
1982                 next = s->isDeclaration();
1983                 if (next == a)
1984                     break;
1985                 if (next == fstart)
1986                     break;
1987             }
1988             else
1989             {
1990                 f = d->isFuncDeclaration();
1991                 if (!f)
1992                 {   d->error("is aliased to a function");
1993                     break;              // BUG: should print error message?
1994                 }
1995                 if ((*fp)(param, f))
1996                     return 1;
1997
1998                 next = f->overnext;
1999             }
2000         }
2001     }
2002     return 0;
2003 }
2004
2005 /********************************************
2006  * If there are no overloads of function f, return that function,
2007  * otherwise return NULL.
2008  */
2009
2010 static int fpunique(void *param, FuncDeclaration *f)
2011 {   FuncDeclaration **pf = (FuncDeclaration **)param;
2012
2013     if (*pf)
2014     {   *pf = NULL;
2015         return 1;               // ambiguous, done
2016     }
2017     else
2018     {   *pf = f;
2019         return 0;
2020     }
2021 }
2022
2023 FuncDeclaration *FuncDeclaration::isUnique()
2024 {   FuncDeclaration *result = NULL;
2025
2026     overloadApply(this, &fpunique, &result);
2027     return result;
2028 }
2029
2030 /********************************************
2031  * Find function in overload list that exactly matches t.
2032  */
2033
2034 struct Param1
2035 {
2036     Type *t;            // type to match
2037     FuncDeclaration *f; // return value
2038 };
2039
2040 int fp1(void *param, FuncDeclaration *f)
2041 {   Param1 *p = (Param1 *)param;
2042     Type *t = p->t;
2043
2044     if (t->equals(f->type))
2045     {   p->f = f;
2046         return 1;
2047     }
2048
2049 #if DMDV2
2050     /* Allow covariant matches, as long as the return type
2051      * is just a const conversion.
2052      * This allows things like pure functions to match with an impure function type.
2053      */
2054     if (t->ty == Tfunction)
2055     {   TypeFunction *tf = (TypeFunction *)f->type;
2056         if (tf->covariant(t) == 1 &&
2057             tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
2058         {
2059             p->f = f;
2060             return 1;
2061         }
2062     }
2063 #endif
2064     return 0;
2065 }
2066
2067 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
2068 {
2069     Param1 p;
2070     p.t = t;
2071     p.f = NULL;
2072     overloadApply(this, &fp1, &p);
2073     return p.f;
2074 }
2075
2076
2077 /********************************************
2078  * Decide which function matches the arguments best.
2079  */
2080
2081 struct Param2
2082 {
2083     Match *m;
2084 #if DMDV2
2085     Expression *ethis;
2086     int property;       // 0: unintialized
2087                         // 1: seen @property
2088                         // 2: not @property
2089 #endif
2090     Expressions *arguments;
2091 };
2092
2093 int fp2(void *param, FuncDeclaration *f)
2094 {   Param2 *p = (Param2 *)param;
2095     Match *m = p->m;
2096     Expressions *arguments = p->arguments;
2097     MATCH match;
2098
2099     if (f != m->lastf)          // skip duplicates
2100     {
2101         m->anyf = f;
2102         TypeFunction *tf = (TypeFunction *)f->type;
2103
2104         int property = (tf->isproperty) ? 1 : 2;
2105         if (p->property == 0)
2106             p->property = property;
2107         else if (p->property != property)
2108             error(f->loc, "cannot overload both property and non-property functions");
2109
2110         /* For constructors, don't worry about the right type of ethis. It's a problem
2111          * anyway, because the constructor attribute may not match the ethis attribute,
2112          * but we don't care because the attribute on the ethis doesn't matter until
2113          * after it's constructed.
2114          */
2115         match = (MATCH) tf->callMatch(f->needThis() && !f->isCtorDeclaration() ? p->ethis : NULL, arguments);
2116         //printf("test1: match = %d\n", match);
2117         if (match != MATCHnomatch)
2118         {
2119             if (match > m->last)
2120                 goto LfIsBetter;
2121
2122             if (match < m->last)
2123                 goto LlastIsBetter;
2124
2125             /* See if one of the matches overrides the other.
2126              */
2127             if (m->lastf->overrides(f))
2128                 goto LlastIsBetter;
2129             else if (f->overrides(m->lastf))
2130                 goto LfIsBetter;
2131
2132 #if DMDV2
2133             /* Try to disambiguate using template-style partial ordering rules.
2134              * In essence, if f() and g() are ambiguous, if f() can call g(),
2135              * but g() cannot call f(), then pick f().
2136              * This is because f() is "more specialized."
2137              */
2138             {
2139             MATCH c1 = f->leastAsSpecialized(m->lastf);
2140             MATCH c2 = m->lastf->leastAsSpecialized(f);
2141             //printf("c1 = %d, c2 = %d\n", c1, c2);
2142             if (c1 > c2)
2143                 goto LfIsBetter;
2144             if (c1 < c2)
2145                 goto LlastIsBetter;
2146             }
2147 #endif
2148         Lambiguous:
2149             m->nextf = f;
2150             m->count++;
2151             return 0;
2152
2153         LfIsBetter:
2154             m->last = match;
2155             m->lastf = f;
2156             m->count = 1;
2157             return 0;
2158
2159         LlastIsBetter:
2160             return 0;
2161         }
2162     }
2163     return 0;
2164 }
2165
2166
2167 void overloadResolveX(Match *m, FuncDeclaration *fstart,
2168         Expression *ethis, Expressions *arguments)
2169 {
2170     Param2 p;
2171     p.m = m;
2172     p.ethis = ethis;
2173     p.property = 0;
2174     p.arguments = arguments;
2175     overloadApply(fstart, &fp2, &p);
2176 }
2177
2178
2179 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags)
2180 {
2181     TypeFunction *tf;
2182     Match m;
2183
2184 #if 0
2185 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
2186 if (arguments)
2187 {   int i;
2188
2189     for (i = 0; i < arguments->dim; i++)
2190     {   Expression *arg;
2191
2192         arg = (Expression *)arguments->data[i];
2193         assert(arg->type);
2194         printf("\t%s: ", arg->toChars());
2195         arg->type->print();
2196     }
2197 }
2198 #endif
2199
2200     memset(&m, 0, sizeof(m));
2201     m.last = MATCHnomatch;
2202     overloadResolveX(&m, this, ethis, arguments);
2203
2204     if (m.count == 1)           // exactly one match
2205     {
2206         return m.lastf;
2207     }
2208     else
2209     {
2210         OutBuffer buf;
2211
2212         buf.writeByte('(');
2213         if (arguments)
2214         {
2215             HdrGenState hgs;
2216
2217             argExpTypesToCBuffer(&buf, arguments, &hgs);
2218             buf.writeByte(')');
2219             if (ethis)
2220                 ethis->type->modToBuffer(&buf);
2221         }
2222         else
2223             buf.writeByte(')');
2224
2225         if (m.last == MATCHnomatch)
2226         {
2227             if (flags & 1)              // if do not print error messages
2228                 return NULL;            // no match
2229
2230             tf = (TypeFunction *)type;
2231
2232             OutBuffer buf2;
2233             tf->modToBuffer(&buf2);
2234
2235             //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
2236             error(loc, "%s%s is not callable using argument types %s",
2237                 Parameter::argsTypesToChars(tf->parameters, tf->varargs),
2238                 buf2.toChars(),
2239                 buf.toChars());
2240             return m.anyf;              // as long as it's not a FuncAliasDeclaration
2241         }
2242         else
2243         {
2244 #if 1
2245             TypeFunction *t1 = (TypeFunction *)m.lastf->type;
2246             TypeFunction *t2 = (TypeFunction *)m.nextf->type;
2247
2248             error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
2249                     buf.toChars(),
2250                     m.lastf->toPrettyChars(), Parameter::argsTypesToChars(t1->parameters, t1->varargs),
2251                     m.nextf->toPrettyChars(), Parameter::argsTypesToChars(t2->parameters, t2->varargs));
2252 #else
2253             error(loc, "overloads %s and %s both match argument list for %s",
2254                     m.lastf->type->toChars(),
2255                     m.nextf->type->toChars(),
2256                     m.lastf->toChars());
2257 #endif
2258             return m.lastf;
2259         }
2260     }
2261 }
2262
2263 /*************************************
2264  * Determine partial specialization order of 'this' vs g.
2265  * This is very similar to TemplateDeclaration::leastAsSpecialized().
2266  * Returns:
2267  *      match   'this' is at least as specialized as g
2268  *      0       g is more specialized than 'this'
2269  */
2270
2271 #if DMDV2
2272 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
2273 {
2274 #define LOG_LEASTAS     0
2275
2276 #if LOG_LEASTAS
2277     printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
2278     printf("%s, %s\n", type->toChars(), g->type->toChars());
2279 #endif
2280
2281     /* This works by calling g() with f()'s parameters, and
2282      * if that is possible, then f() is at least as specialized
2283      * as g() is.
2284      */
2285
2286     TypeFunction *tf = (TypeFunction *)type;
2287     TypeFunction *tg = (TypeFunction *)g->type;
2288     size_t nfparams = Parameter::dim(tf->parameters);
2289     size_t ngparams = Parameter::dim(tg->parameters);
2290     MATCH match = MATCHexact;
2291
2292     /* If both functions have a 'this' pointer, and the mods are not
2293      * the same and g's is not const, then this is less specialized.
2294      */
2295     if (needThis() && g->needThis())
2296     {
2297         if (tf->mod != tg->mod)
2298         {
2299             if (tg->mod == MODconst)
2300                 match = MATCHconst;
2301             else
2302                 return MATCHnomatch;
2303         }
2304     }
2305
2306     /* Create a dummy array of arguments out of the parameters to f()
2307      */
2308     Expressions args;
2309     args.setDim(nfparams);
2310     for (int u = 0; u < nfparams; u++)
2311     {
2312         Parameter *p = Parameter::getNth(tf->parameters, u);
2313         Expression *e;
2314         if (p->storageClass & (STCref | STCout))
2315         {
2316             e = new IdentifierExp(0, p->ident);
2317             e->type = p->type;
2318         }
2319         else
2320             e = p->type->defaultInit();
2321         args.data[u] = e;
2322     }
2323
2324     MATCH m = (MATCH) tg->callMatch(NULL, &args, 1);
2325     if (m)
2326     {
2327         /* A variadic parameter list is less specialized than a
2328          * non-variadic one.
2329          */
2330         if (tf->varargs && !tg->varargs)
2331             goto L1;    // less specialized
2332
2333 #if LOG_LEASTAS
2334         printf("  matches %d, so is least as specialized\n", m);
2335 #endif
2336         return m;
2337     }
2338   L1:
2339 #if LOG_LEASTAS
2340     printf("  doesn't match, so is not as specialized\n");
2341 #endif
2342     return MATCHnomatch;
2343 }
2344
2345 /*******************************************
2346  * Given a symbol that could be either a FuncDeclaration or
2347  * a function template, resolve it to a function symbol.
2348  *      sc              instantiation scope
2349  *      loc             instantiation location
2350  *      targsi          initial list of template arguments
2351  *      ethis           if !NULL, the 'this' pointer argument
2352  *      fargs           arguments to function
2353  *      flags           1: do not issue error message on no match, just return NULL
2354  */
2355
2356 FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
2357         Objects *tiargs,
2358         Expression *ethis,
2359         Expressions *arguments,
2360         int flags)
2361 {
2362     if (!s)
2363         return NULL;                    // no match
2364     FuncDeclaration *f = s->isFuncDeclaration();
2365     if (f)
2366         f = f->overloadResolve(loc, ethis, arguments);
2367     else
2368     {   TemplateDeclaration *td = s->isTemplateDeclaration();
2369         assert(td);
2370         f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags);
2371     }
2372     return f;
2373 }
2374 #endif
2375
2376 /********************************
2377  * Labels are in a separate scope, one per function.
2378  */
2379
2380 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
2381 {   Dsymbol *s;
2382
2383     if (!labtab)
2384         labtab = new DsymbolTable();    // guess we need one
2385
2386     s = labtab->lookup(ident);
2387     if (!s)
2388     {
2389         s = new LabelDsymbol(ident);
2390         labtab->insert(s);
2391     }
2392     return (LabelDsymbol *)s;
2393 }
2394
2395 /****************************************
2396  * If non-static member function that has a 'this' pointer,
2397  * return the aggregate it is a member of.
2398  * Otherwise, return NULL.
2399  */
2400
2401 AggregateDeclaration *FuncDeclaration::isThis()
2402 {   AggregateDeclaration *ad;
2403
2404     //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
2405     ad = NULL;
2406     if ((storage_class & STCstatic) == 0)
2407     {
2408         ad = isMember2();
2409     }
2410     //printf("-FuncDeclaration::isThis() %p\n", ad);
2411     return ad;
2412 }
2413
2414 AggregateDeclaration *FuncDeclaration::isMember2()
2415 {   AggregateDeclaration *ad;
2416
2417     //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
2418     ad = NULL;
2419     for (Dsymbol *s = this; s; s = s->parent)
2420     {
2421 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
2422         ad = s->isMember();
2423         if (ad)
2424 {
2425             break;
2426 }
2427         if (!s->parent ||
2428             (!s->parent->isTemplateInstance()))
2429 {
2430             break;
2431 }
2432     }
2433     //printf("-FuncDeclaration::isMember2() %p\n", ad);
2434     return ad;
2435 }
2436
2437 /*****************************************
2438  * Determine lexical level difference from 'this' to nested function 'fd'.
2439  * Error if this cannot call fd.
2440  * Returns:
2441  *      0       same level
2442  *      -1      increase nesting by 1 (fd is nested within 'this')
2443  *      >0      decrease nesting by number
2444  */
2445
2446 int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
2447 {   int level;
2448     Dsymbol *s;
2449     Dsymbol *fdparent;
2450
2451     //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
2452     fdparent = fd->toParent2();
2453     if (fdparent == this)
2454         return -1;
2455     s = this;
2456     level = 0;
2457     while (fd != s && fdparent != s->toParent2())
2458     {
2459         //printf("\ts = %s, '%s'\n", s->kind(), s->toChars());
2460         FuncDeclaration *thisfd = s->isFuncDeclaration();
2461         if (thisfd)
2462         {   if (!thisfd->isNested() && !thisfd->vthis)
2463                 goto Lerr;
2464         }
2465         else
2466         {
2467             AggregateDeclaration *thiscd = s->isAggregateDeclaration();
2468             if (thiscd)
2469             {   if (!thiscd->isNested())
2470                     goto Lerr;
2471             }
2472             else
2473                 goto Lerr;
2474         }
2475
2476         s = s->toParent2();
2477         assert(s);
2478         level++;
2479     }
2480     return level;
2481
2482 Lerr:
2483     error(loc, "cannot access frame of function %s", fd->toPrettyChars());
2484     return 1;
2485 }
2486
2487 void FuncDeclaration::appendExp(Expression *e)
2488 {   Statement *s;
2489
2490     s = new ExpStatement(0, e);
2491     appendState(s);
2492 }
2493
2494 void FuncDeclaration::appendState(Statement *s)
2495 {
2496     if (!fbody)
2497         fbody = s;
2498     else
2499     {
2500         CompoundStatement *cs = fbody->isCompoundStatement();
2501         if (cs)
2502         {
2503             if (!cs->statements)
2504                 fbody = s;
2505             else
2506                 cs->statements->push(s);
2507         }
2508         else
2509             fbody = new CompoundStatement(0, fbody, s);
2510     }
2511 }
2512
2513 const char *FuncDeclaration::toPrettyChars()
2514 {
2515     if (isMain())
2516         return "D main";
2517     else
2518         return Dsymbol::toPrettyChars();
2519 }
2520
2521 int FuncDeclaration::isMain()
2522 {
2523     return ident == Id::main &&
2524         linkage != LINKc && !isMember() && !isNested();
2525 }
2526
2527 int FuncDeclaration::isWinMain()
2528 {
2529     //printf("FuncDeclaration::isWinMain() %s\n", toChars());
2530 #if 0
2531     int x = ident == Id::WinMain &&
2532         linkage != LINKc && !isMember();
2533     printf("%s\n", x ? "yes" : "no");
2534     return x;
2535 #else
2536     return ident == Id::WinMain &&
2537         linkage != LINKc && !isMember();
2538 #endif
2539 }
2540
2541 int FuncDeclaration::isDllMain()
2542 {
2543     return ident == Id::DllMain &&
2544         linkage != LINKc && !isMember();
2545 }
2546
2547 int FuncDeclaration::isExport()
2548 {
2549     return protection == PROTexport;
2550 }
2551
2552 int FuncDeclaration::isImportedSymbol()
2553 {
2554     //printf("isImportedSymbol()\n");
2555     //printf("protection = %d\n", protection);
2556     return (protection == PROTexport) && !fbody;
2557 }
2558
2559 // Determine if function goes into virtual function pointer table
2560
2561 int FuncDeclaration::isVirtual()
2562 {
2563 #if 0
2564     printf("FuncDeclaration::isVirtual(%s)\n", toChars());
2565     printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2566     printf("result is %d\n",
2567         isMember() &&
2568         !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2569         toParent()->isClassDeclaration());
2570 #endif
2571     Dsymbol *p = toParent();
2572     return isMember() &&
2573         !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2574         p->isClassDeclaration() &&
2575         !(p->isInterfaceDeclaration() && isFinal());
2576 }
2577
2578 int FuncDeclaration::isFinal()
2579 {
2580     ClassDeclaration *cd;
2581 #if 0
2582     printf("FuncDeclaration::isFinal(%s), %x\n", toChars(), Declaration::isFinal());
2583     printf("%p %d %d %d\n", isMember(), isStatic(), Declaration::isFinal(), ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2584     printf("result is %d\n",
2585         isMember() &&
2586         (Declaration::isFinal() ||
2587          ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal)));
2588     if (cd)
2589         printf("\tmember of %s\n", cd->toChars());
2590 #if 0
2591         !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2592         (cd = toParent()->isClassDeclaration()) != NULL &&
2593         cd->storage_class & STCfinal);
2594 #endif
2595 #endif
2596     return isMember() &&
2597         (Declaration::isFinal() ||
2598          ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2599 }
2600
2601 int FuncDeclaration::isAbstract()
2602 {
2603     return storage_class & STCabstract;
2604 }
2605
2606 int FuncDeclaration::isCodeseg()
2607 {
2608     return TRUE;                // functions are always in the code segment
2609 }
2610
2611 int FuncDeclaration::isOverloadable()
2612 {
2613     return 1;                   // functions can be overloaded
2614 }
2615
2616 enum PURE FuncDeclaration::isPure()
2617 {
2618     //printf("FuncDeclaration::isPure() '%s'\n", toChars());
2619     assert(type->ty == Tfunction);
2620     TypeFunction *tf = (TypeFunction *)type;
2621     enum PURE purity = tf->purity;
2622     if (purity == PUREfwdref)
2623         tf->purityLevel();
2624     if (purity > PUREweak && needThis())
2625     {   // The attribute of the 'this' reference affects purity strength
2626         if (type->mod & (MODimmutable | MODwild))
2627             ;
2628         else if (type->mod & MODconst && purity >= PUREconst)
2629             purity = PUREconst;
2630         else
2631             purity = PUREweak;
2632     }
2633     return purity;
2634 }
2635
2636 int FuncDeclaration::isSafe()
2637 {
2638     assert(type->ty == Tfunction);
2639     return ((TypeFunction *)type)->trust == TRUSTsafe;
2640 }
2641
2642 int FuncDeclaration::isTrusted()
2643 {
2644     assert(type->ty == Tfunction);
2645     return ((TypeFunction *)type)->trust == TRUSTtrusted;
2646 }
2647
2648 // Determine if function needs
2649 // a static frame pointer to its lexically enclosing function
2650
2651 int FuncDeclaration::isNested()
2652 {
2653     //if (!toParent())
2654         //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2655     //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2656     return ((storage_class & STCstatic) == 0) &&
2657            (toParent2()->isFuncDeclaration() != NULL);
2658 }
2659
2660 int FuncDeclaration::needThis()
2661 {
2662     //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2663     int i = isThis() != NULL;
2664     //printf("\t%d\n", i);
2665     if (!i && isFuncAliasDeclaration())
2666         i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
2667     return i;
2668 }
2669
2670 int FuncDeclaration::addPreInvariant()
2671 {
2672     AggregateDeclaration *ad = isThis();
2673     return (ad &&
2674             //ad->isClassDeclaration() &&
2675             global.params.useInvariants &&
2676             (protection == PROTpublic || protection == PROTexport) &&
2677             !naked &&
2678             ident != Id::cpctor);
2679 }
2680
2681 int FuncDeclaration::addPostInvariant()
2682 {
2683     AggregateDeclaration *ad = isThis();
2684     return (ad &&
2685             ad->inv &&
2686             //ad->isClassDeclaration() &&
2687             global.params.useInvariants &&
2688             (protection == PROTpublic || protection == PROTexport) &&
2689             !naked &&
2690             ident != Id::cpctor);
2691 }
2692
2693 /**********************************
2694  * Generate a FuncDeclaration for a runtime library function.
2695  */
2696
2697 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, const char *name)
2698 {
2699     return genCfunc(treturn, Lexer::idPool(name));
2700 }
2701
2702 FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id)
2703 {
2704     FuncDeclaration *fd;
2705     TypeFunction *tf;
2706     Dsymbol *s;
2707     static DsymbolTable *st = NULL;
2708
2709     //printf("genCfunc(name = '%s')\n", id->toChars());
2710     //printf("treturn\n\t"); treturn->print();
2711
2712     // See if already in table
2713     if (!st)
2714         st = new DsymbolTable();
2715     s = st->lookup(id);
2716     if (s)
2717     {
2718         fd = s->isFuncDeclaration();
2719         assert(fd);
2720         assert(fd->type->nextOf()->equals(treturn));
2721     }
2722     else
2723     {
2724         tf = new TypeFunction(NULL, treturn, 0, LINKc);
2725         fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2726         fd->protection = PROTpublic;
2727         fd->linkage = LINKc;
2728
2729         st->insert(fd);
2730     }
2731     return fd;
2732 }
2733
2734 const char *FuncDeclaration::kind()
2735 {
2736     return "function";
2737 }
2738
2739 /*******************************
2740  * Look at all the variables in this function that are referenced
2741  * by nested functions, and determine if a closure needs to be
2742  * created for them.
2743  */
2744
2745 #if DMDV2
2746 int FuncDeclaration::needsClosure()
2747 {
2748     /* Need a closure for all the closureVars[] if any of the
2749      * closureVars[] are accessed by a
2750      * function that escapes the scope of this function.
2751      * We take the conservative approach and decide that any function that:
2752      * 1) is a virtual function
2753      * 2) has its address taken
2754      * 3) has a parent that escapes
2755      *
2756      * Note that since a non-virtual function can be called by
2757      * a virtual one, if that non-virtual function accesses a closure
2758      * var, the closure still has to be taken. Hence, we check for isThis()
2759      * instead of isVirtual(). (thanks to David Friedman)
2760      */
2761
2762     //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2763     for (int i = 0; i < closureVars.dim; i++)
2764     {   VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
2765         assert(v->isVarDeclaration());
2766         //printf("\tv = %s\n", v->toChars());
2767
2768         for (int j = 0; j < v->nestedrefs.dim; j++)
2769         {   FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
2770             assert(f != this);
2771
2772             //printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
2773             if (f->isThis() || f->tookAddressOf)
2774                 goto Lyes;      // assume f escapes this function's scope
2775
2776             // Look to see if any parents of f that are below this escape
2777             for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
2778             {
2779                 f = s->isFuncDeclaration();
2780                 if (f && (f->isThis() || f->tookAddressOf))
2781                     goto Lyes;
2782             }
2783         }
2784     }
2785     return 0;
2786
2787 Lyes:
2788     //printf("\tneeds closure\n");
2789     return 1;
2790 }
2791 #endif
2792
2793 /*********************************************
2794  * Return the function's parameter list, and whether
2795  * it is variadic or not.
2796  */
2797
2798 Parameters *FuncDeclaration::getParameters(int *pvarargs)
2799 {   Parameters *fparameters;
2800     int fvarargs;
2801
2802     if (type)
2803     {
2804         assert(type->ty == Tfunction);
2805         TypeFunction *fdtype = (TypeFunction *)type;
2806         fparameters = fdtype->parameters;
2807         fvarargs = fdtype->varargs;
2808     }
2809     else // Constructors don't have type's
2810     {   CtorDeclaration *fctor = isCtorDeclaration();
2811         assert(fctor);
2812         fparameters = fctor->arguments;
2813         fvarargs = fctor->varargs;
2814     }
2815     if (pvarargs)
2816         *pvarargs = fvarargs;
2817     return fparameters;
2818 }
2819
2820
2821 /****************************** FuncAliasDeclaration ************************/
2822
2823 // Used as a way to import a set of functions from another scope into this one.
2824
2825 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2826     : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2827         funcalias->storage_class, funcalias->type)
2828 {
2829     assert(funcalias != this);
2830     this->funcalias = funcalias;
2831 }
2832
2833 const char *FuncAliasDeclaration::kind()
2834 {
2835     return "function alias";
2836 }
2837
2838
2839 /****************************** FuncLiteralDeclaration ************************/
2840
2841 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2842         enum TOK tok, ForeachStatement *fes)
2843     : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2844 {
2845     const char *id;
2846
2847     if (fes)
2848         id = "__foreachbody";
2849     else if (tok == TOKdelegate)
2850         id = "__dgliteral";
2851     else
2852         id = "__funcliteral";
2853     this->ident = Lexer::uniqueId(id);
2854     this->tok = tok;
2855     this->fes = fes;
2856     //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2857 }
2858
2859 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2860 {
2861     FuncLiteralDeclaration *f;
2862
2863     //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2864     if (s)
2865         f = (FuncLiteralDeclaration *)s;
2866     else
2867     {   f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2868         f->ident = ident;               // keep old identifier
2869     }
2870     FuncDeclaration::syntaxCopy(f);
2871     return f;
2872 }
2873
2874 int FuncLiteralDeclaration::isNested()
2875 {
2876     //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2877     return (tok == TOKdelegate);
2878 }
2879
2880 int FuncLiteralDeclaration::isVirtual()
2881 {
2882     return FALSE;
2883 }
2884
2885 const char *FuncLiteralDeclaration::kind()
2886 {
2887     // GCC requires the (char*) casts
2888     return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
2889 }
2890
2891 void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2892 {
2893     buf->writestring(kind());
2894     buf->writeByte(' ');
2895     type->toCBuffer(buf, NULL, hgs);
2896     bodyToCBuffer(buf, hgs);
2897 }
2898
2899
2900 /********************************* CtorDeclaration ****************************/
2901
2902 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Parameters *arguments, int varargs, StorageClass stc)
2903     : FuncDeclaration(loc, endloc, Id::ctor, stc, NULL)
2904 {
2905     this->arguments = arguments;
2906     this->varargs = varargs;
2907     //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
2908 }
2909
2910 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
2911 {
2912     CtorDeclaration *f = new CtorDeclaration(loc, endloc, NULL, varargs, storage_class);
2913
2914     f->outId = outId;
2915     f->frequire = frequire ? frequire->syntaxCopy() : NULL;
2916     f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
2917     f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
2918     assert(!fthrows); // deprecated
2919
2920     f->arguments = Parameter::arraySyntaxCopy(arguments);
2921     return f;
2922 }
2923
2924
2925 void CtorDeclaration::semantic(Scope *sc)
2926 {
2927     //printf("CtorDeclaration::semantic() %s\n", toChars());
2928     sc = sc->push();
2929     sc->stc &= ~STCstatic;              // not a static constructor
2930
2931     parent = sc->parent;
2932     Dsymbol *parent = toParent2();
2933     Type *tret;
2934     AggregateDeclaration *ad = parent->isAggregateDeclaration();
2935     if (!ad || parent->isUnionDeclaration())
2936     {
2937         error("constructors are only for class or struct definitions");
2938         tret = Type::tvoid;
2939     }
2940     else
2941     {   tret = ad->handle;
2942         assert(tret);
2943         tret = tret->addStorageClass(storage_class | sc->stc);
2944     }
2945     if (!type)
2946         type = new TypeFunction(arguments, tret, varargs, LINKd, storage_class | sc->stc);
2947
2948 #if STRUCTTHISREF
2949     if (ad && ad->isStructDeclaration())
2950     {   ((TypeFunction *)type)->isref = 1;
2951         if (!originalType)
2952             // Leave off the "ref"
2953             originalType = new TypeFunction(arguments, tret, varargs, LINKd, storage_class | sc->stc);
2954     }
2955 #endif
2956     if (!originalType)
2957         originalType = type;
2958
2959     // Append:
2960     //  return this;
2961     // to the function body
2962     if (fbody && semanticRun < PASSsemantic)
2963     {
2964         Expression *e = new ThisExp(loc);
2965         if (parent->isClassDeclaration())
2966             e->type = tret;
2967         Statement *s = new ReturnStatement(loc, e);
2968         fbody = new CompoundStatement(loc, fbody, s);
2969     }
2970
2971     FuncDeclaration::semantic(sc);
2972
2973     sc->pop();
2974
2975     // See if it's the default constructor
2976     if (ad && varargs == 0 && Parameter::dim(arguments) == 0)
2977     {   if (ad->isStructDeclaration())
2978             error("default constructor not allowed for structs");
2979         else
2980             ad->defaultCtor = this;
2981     }
2982 }
2983
2984 const char *CtorDeclaration::kind()
2985 {
2986     return "constructor";
2987 }
2988
2989 char *CtorDeclaration::toChars()
2990 {
2991     return (char *)"this";
2992 }
2993
2994 int CtorDeclaration::isVirtual()
2995 {
2996     return FALSE;
2997 }
2998
2999 int CtorDeclaration::addPreInvariant()
3000 {
3001     return FALSE;
3002 }
3003
3004 int CtorDeclaration::addPostInvariant()
3005 {
3006     return (isThis() && vthis && global.params.useInvariants);
3007 }
3008
3009
3010 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3011 {
3012     if (originalType && originalType->ty == Tfunction)
3013         ((TypeFunction *)originalType)->attributesToCBuffer(buf, 0);
3014     buf->writestring("this");
3015     Parameter::argsToCBuffer(buf, hgs, arguments, varargs);
3016     bodyToCBuffer(buf, hgs);
3017 }
3018
3019 /********************************* PostBlitDeclaration ****************************/
3020
3021 #if DMDV2
3022 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
3023     : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
3024 {
3025 }
3026
3027 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
3028     : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
3029 {
3030 }
3031
3032 Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
3033 {
3034     assert(!s);
3035     PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
3036     return FuncDeclaration::syntaxCopy(dd);
3037 }
3038
3039
3040 void PostBlitDeclaration::semantic(Scope *sc)
3041 {
3042     //printf("PostBlitDeclaration::semantic() %s\n", toChars());
3043     //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
3044     //printf("stc = x%llx\n", sc->stc);
3045     parent = sc->parent;
3046     Dsymbol *parent = toParent();
3047     StructDeclaration *ad = parent->isStructDeclaration();
3048     if (!ad)
3049     {
3050         error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
3051     }
3052     else if (ident == Id::_postblit && semanticRun < PASSsemantic)
3053         ad->postblits.push(this);
3054
3055     if (!type)
3056         type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3057
3058     sc = sc->push();
3059     sc->stc &= ~STCstatic;              // not static
3060     sc->linkage = LINKd;
3061
3062     FuncDeclaration::semantic(sc);
3063
3064     sc->pop();
3065 }
3066
3067 int PostBlitDeclaration::overloadInsert(Dsymbol *s)
3068 {
3069     return FALSE;       // cannot overload postblits
3070 }
3071
3072 int PostBlitDeclaration::addPreInvariant()
3073 {
3074     return FALSE;
3075 }
3076
3077 int PostBlitDeclaration::addPostInvariant()
3078 {
3079     return (isThis() && vthis && global.params.useInvariants);
3080 }
3081
3082 int PostBlitDeclaration::isVirtual()
3083 {
3084     return FALSE;
3085 }
3086
3087 void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3088 {
3089     buf->writestring("this(this)");
3090     bodyToCBuffer(buf, hgs);
3091 }
3092 #endif
3093
3094 /********************************* DtorDeclaration ****************************/
3095
3096 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
3097     : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
3098 {
3099 }
3100
3101 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
3102     : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
3103 {
3104 }
3105
3106 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
3107 {
3108     assert(!s);
3109     DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
3110     return FuncDeclaration::syntaxCopy(dd);
3111 }
3112
3113
3114 void DtorDeclaration::semantic(Scope *sc)
3115 {
3116     //printf("DtorDeclaration::semantic() %s\n", toChars());
3117     //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
3118     parent = sc->parent;
3119     Dsymbol *parent = toParent();
3120     AggregateDeclaration *ad = parent->isAggregateDeclaration();
3121     if (!ad)
3122     {
3123         error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
3124     }
3125     else if (ident == Id::dtor && semanticRun < PASSsemantic)
3126         ad->dtors.push(this);
3127
3128     if (!type)
3129         type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3130
3131     sc = sc->push();
3132     sc->stc &= ~STCstatic;              // not a static destructor
3133     sc->linkage = LINKd;
3134
3135     FuncDeclaration::semantic(sc);
3136
3137     sc->pop();
3138 }
3139
3140 int DtorDeclaration::overloadInsert(Dsymbol *s)
3141 {
3142     return FALSE;       // cannot overload destructors
3143 }
3144
3145 int DtorDeclaration::addPreInvariant()
3146 {
3147     return (isThis() && vthis && global.params.useInvariants);
3148 }
3149
3150 int DtorDeclaration::addPostInvariant()
3151 {
3152     return FALSE;
3153 }
3154
3155 const char *DtorDeclaration::kind()
3156 {
3157     return "destructor";
3158 }
3159
3160 char *DtorDeclaration::toChars()
3161 {
3162     return (char *)"~this";
3163 }
3164
3165 int DtorDeclaration::isVirtual()
3166 {
3167     /* This should be FALSE so that dtor's don't get put into the vtbl[],
3168      * but doing so will require recompiling everything.
3169      */
3170 #if BREAKABI
3171     return FALSE;
3172 #else
3173     return FuncDeclaration::isVirtual();
3174 #endif
3175 }
3176
3177 void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3178 {
3179     buf->writestring("~this()");
3180     bodyToCBuffer(buf, hgs);
3181 }
3182
3183 /********************************* StaticCtorDeclaration ****************************/
3184
3185 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
3186     : FuncDeclaration(loc, endloc,
3187       Identifier::generateId("_staticCtor"), STCstatic, NULL)
3188 {
3189 }
3190
3191 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, const char *name)
3192     : FuncDeclaration(loc, endloc,
3193       Identifier::generateId(name), STCstatic, NULL)
3194 {
3195 }
3196
3197 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
3198 {
3199     assert(!s);
3200     StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc);
3201     return FuncDeclaration::syntaxCopy(scd);
3202 }
3203
3204
3205 void StaticCtorDeclaration::semantic(Scope *sc)
3206 {
3207     //printf("StaticCtorDeclaration::semantic()\n");
3208
3209     if (!type)
3210         type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3211
3212     /* If the static ctor appears within a template instantiation,
3213      * it could get called multiple times by the module constructors
3214      * for different modules. Thus, protect it with a gate.
3215      */
3216     if (inTemplateInstance() && semanticRun < PASSsemantic)
3217     {
3218         /* Add this prefix to the function:
3219          *      static int gate;
3220          *      if (++gate != 1) return;
3221          * Note that this is not thread safe; should not have threads
3222          * during static construction.
3223          */
3224         Identifier *id = Lexer::idPool("__gate");
3225         VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
3226         v->storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls;
3227         Statements *sa = new Statements();
3228         Statement *s = new DeclarationStatement(0, v);
3229         sa->push(s);
3230         Expression *e = new IdentifierExp(0, id);
3231         e = new AddAssignExp(0, e, new IntegerExp(1));
3232         e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
3233         s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
3234         sa->push(s);
3235         if (fbody)
3236             sa->push(fbody);
3237         fbody = new CompoundStatement(0, sa);
3238     }
3239
3240     FuncDeclaration::semantic(sc);
3241
3242     // We're going to need ModuleInfo
3243     Module *m = getModule();
3244     if (!m)
3245         m = sc->module;
3246     if (m)
3247     {   m->needmoduleinfo = 1;
3248         //printf("module1 %s needs moduleinfo\n", m->toChars());
3249 #ifdef IN_GCC
3250         m->strictlyneedmoduleinfo = 1;
3251 #endif
3252     }
3253 }
3254
3255 AggregateDeclaration *StaticCtorDeclaration::isThis()
3256 {
3257     return NULL;
3258 }
3259
3260 int StaticCtorDeclaration::isVirtual()
3261 {
3262     return FALSE;
3263 }
3264
3265 int StaticCtorDeclaration::addPreInvariant()
3266 {
3267     return FALSE;
3268 }
3269
3270 int StaticCtorDeclaration::addPostInvariant()
3271 {
3272     return FALSE;
3273 }
3274
3275 void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3276 {
3277     if (hgs->hdrgen)
3278     {   buf->writestring("static this();\n");
3279         return;
3280     }
3281     buf->writestring("static this()");
3282     bodyToCBuffer(buf, hgs);
3283 }
3284
3285 /********************************* SharedStaticCtorDeclaration ****************************/
3286
3287 SharedStaticCtorDeclaration::SharedStaticCtorDeclaration(Loc loc, Loc endloc)
3288     : StaticCtorDeclaration(loc, endloc, "_sharedStaticCtor")
3289 {
3290 }
3291
3292 Dsymbol *SharedStaticCtorDeclaration::syntaxCopy(Dsymbol *s)
3293 {
3294     assert(!s);
3295     SharedStaticCtorDeclaration *scd = new SharedStaticCtorDeclaration(loc, endloc);
3296     return FuncDeclaration::syntaxCopy(scd);
3297 }
3298
3299 void SharedStaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3300 {
3301     buf->writestring("shared ");
3302     StaticCtorDeclaration::toCBuffer(buf, hgs);
3303 }
3304
3305 /********************************* StaticDtorDeclaration ****************************/
3306
3307 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
3308     : FuncDeclaration(loc, endloc,
3309       Identifier::generateId("_staticDtor"), STCstatic, NULL)
3310 {
3311     vgate = NULL;
3312 }
3313
3314 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, const char *name)
3315     : FuncDeclaration(loc, endloc,
3316       Identifier::generateId(name), STCstatic, NULL)
3317 {
3318     vgate = NULL;
3319 }
3320
3321 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
3322 {
3323     assert(!s);
3324     StaticDtorDeclaration *sdd = new StaticDtorDeclaration(loc, endloc);
3325     return FuncDeclaration::syntaxCopy(sdd);
3326 }
3327
3328
3329 void StaticDtorDeclaration::semantic(Scope *sc)
3330 {
3331     ClassDeclaration *cd = sc->scopesym->isClassDeclaration();
3332
3333     if (!type)
3334         type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3335
3336     /* If the static ctor appears within a template instantiation,
3337      * it could get called multiple times by the module constructors
3338      * for different modules. Thus, protect it with a gate.
3339      */
3340     if (inTemplateInstance() && semanticRun < PASSsemantic)
3341     {
3342         /* Add this prefix to the function:
3343          *      static int gate;
3344          *      if (--gate != 0) return;
3345          * Increment gate during constructor execution.
3346          * Note that this is not thread safe; should not have threads
3347          * during static destruction.
3348          */
3349         Identifier *id = Lexer::idPool("__gate");
3350         VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
3351         v->storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls;
3352         Statements *sa = new Statements();
3353         Statement *s = new DeclarationStatement(0, v);
3354         sa->push(s);
3355         Expression *e = new IdentifierExp(0, id);
3356         e = new AddAssignExp(0, e, new IntegerExp(-1));
3357         e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0));
3358         s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
3359         sa->push(s);
3360         if (fbody)
3361             sa->push(fbody);
3362         fbody = new CompoundStatement(0, sa);
3363         vgate = v;
3364     }
3365
3366     FuncDeclaration::semantic(sc);
3367
3368     // We're going to need ModuleInfo
3369     Module *m = getModule();
3370     if (!m)
3371         m = sc->module;
3372     if (m)
3373     {   m->needmoduleinfo = 1;
3374         //printf("module2 %s needs moduleinfo\n", m->toChars());
3375 #ifdef IN_GCC
3376         m->strictlyneedmoduleinfo = 1;
3377 #endif
3378     }
3379 }
3380
3381 AggregateDeclaration *StaticDtorDeclaration::isThis()
3382 {
3383     return NULL;
3384 }
3385
3386 int StaticDtorDeclaration::isVirtual()
3387 {
3388     return FALSE;
3389 }
3390
3391 int StaticDtorDeclaration::addPreInvariant()
3392 {
3393     return FALSE;
3394 }
3395
3396 int StaticDtorDeclaration::addPostInvariant()
3397 {
3398     return FALSE;
3399 }
3400
3401 void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3402 {
3403     if (hgs->hdrgen)
3404         return;
3405     buf->writestring("static ~this()");
3406     bodyToCBuffer(buf, hgs);
3407 }
3408
3409 /********************************* SharedStaticDtorDeclaration ****************************/
3410
3411 SharedStaticDtorDeclaration::SharedStaticDtorDeclaration(Loc loc, Loc endloc)
3412     : StaticDtorDeclaration(loc, endloc, "_sharedStaticDtor")
3413 {
3414 }
3415
3416 Dsymbol *SharedStaticDtorDeclaration::syntaxCopy(Dsymbol *s)
3417 {
3418     assert(!s);
3419     SharedStaticDtorDeclaration *sdd = new SharedStaticDtorDeclaration(loc, endloc);
3420     return FuncDeclaration::syntaxCopy(sdd);
3421 }
3422
3423 void SharedStaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3424 {
3425     if (!hgs->hdrgen)
3426     {
3427         buf->writestring("shared ");
3428         StaticDtorDeclaration::toCBuffer(buf, hgs);
3429     }
3430 }
3431
3432
3433 /********************************* InvariantDeclaration ****************************/
3434
3435 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
3436     : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
3437 {
3438 }
3439
3440 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
3441 {
3442     InvariantDeclaration *id;
3443
3444     assert(!s);
3445     id = new InvariantDeclaration(loc, endloc);
3446     FuncDeclaration::syntaxCopy(id);
3447     return id;
3448 }
3449
3450
3451 void InvariantDeclaration::semantic(Scope *sc)
3452 {
3453     parent = sc->parent;
3454     Dsymbol *parent = toParent();
3455     AggregateDeclaration *ad = parent->isAggregateDeclaration();
3456     if (!ad)
3457     {
3458         error("invariants are only for struct/union/class definitions");
3459         return;
3460     }
3461     else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic)
3462     {
3463         error("more than one invariant for %s", ad->toChars());
3464     }
3465     ad->inv = this;
3466     if (!type)
3467         type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3468
3469     sc = sc->push();
3470     sc->stc &= ~STCstatic;              // not a static invariant
3471     sc->incontract++;
3472     sc->linkage = LINKd;
3473
3474     FuncDeclaration::semantic(sc);
3475
3476     sc->pop();
3477 }
3478
3479 int InvariantDeclaration::isVirtual()
3480 {
3481     return FALSE;
3482 }
3483
3484 int InvariantDeclaration::addPreInvariant()
3485 {
3486     return FALSE;
3487 }
3488
3489 int InvariantDeclaration::addPostInvariant()
3490 {
3491     return FALSE;
3492 }
3493
3494 void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3495 {
3496     if (hgs->hdrgen)
3497         return;
3498     buf->writestring("invariant");
3499     bodyToCBuffer(buf, hgs);
3500 }
3501
3502
3503 /********************************* UnitTestDeclaration ****************************/
3504
3505 /*******************************
3506  * Generate unique unittest function Id so we can have multiple
3507  * instances per module.
3508  */
3509
3510 static Identifier *unitTestId()
3511 {
3512     return Lexer::uniqueId("__unittest");
3513 }
3514
3515 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
3516     : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
3517 {
3518 }
3519
3520 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
3521 {
3522     UnitTestDeclaration *utd;
3523
3524     assert(!s);
3525     utd = new UnitTestDeclaration(loc, endloc);
3526     return FuncDeclaration::syntaxCopy(utd);
3527 }
3528
3529
3530 void UnitTestDeclaration::semantic(Scope *sc)
3531 {
3532     if (global.params.useUnitTests)
3533     {
3534         if (!type)
3535             type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3536         Scope *sc2 = sc->push();
3537         // It makes no sense for unit tests to be pure or nothrow.
3538         sc2->stc &= ~(STCnothrow | STCpure);
3539         sc2->linkage = LINKd;
3540         FuncDeclaration::semantic(sc2);
3541         sc2->pop();
3542     }
3543
3544 #if 0
3545     // We're going to need ModuleInfo even if the unit tests are not
3546     // compiled in, because other modules may import this module and refer
3547     // to this ModuleInfo.
3548     // (This doesn't make sense to me?)
3549     Module *m = getModule();
3550     if (!m)
3551         m = sc->module;
3552     if (m)
3553     {
3554         //printf("module3 %s needs moduleinfo\n", m->toChars());
3555         m->needmoduleinfo = 1;
3556     }
3557 #endif
3558 }
3559
3560 AggregateDeclaration *UnitTestDeclaration::isThis()
3561 {
3562     return NULL;
3563 }
3564
3565 int UnitTestDeclaration::isVirtual()
3566 {
3567     return FALSE;
3568 }
3569
3570 int UnitTestDeclaration::addPreInvariant()
3571 {
3572     return FALSE;
3573 }
3574
3575 int UnitTestDeclaration::addPostInvariant()
3576 {
3577     return FALSE;
3578 }
3579
3580 void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3581 {
3582     if (hgs->hdrgen)
3583         return;
3584     buf->writestring("unittest");
3585     bodyToCBuffer(buf, hgs);
3586 }
3587
3588 /********************************* NewDeclaration ****************************/
3589
3590 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Parameters *arguments, int varargs)
3591     : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
3592 {
3593     this->arguments = arguments;
3594     this->varargs = varargs;
3595 }
3596
3597 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
3598 {
3599     NewDeclaration *f;
3600
3601     f = new NewDeclaration(loc, endloc, NULL, varargs);
3602
3603     FuncDeclaration::syntaxCopy(f);
3604
3605     f->arguments = Parameter::arraySyntaxCopy(arguments);
3606
3607     return f;
3608 }
3609
3610
3611 void NewDeclaration::semantic(Scope *sc)
3612 {
3613     //printf("NewDeclaration::semantic()\n");
3614
3615     parent = sc->parent;
3616     Dsymbol *parent = toParent();
3617     ClassDeclaration *cd = parent->isClassDeclaration();
3618     if (!cd && !parent->isStructDeclaration())
3619     {
3620         error("new allocators only are for class or struct definitions");
3621     }
3622     Type *tret = Type::tvoid->pointerTo();
3623     if (!type)
3624         type = new TypeFunction(arguments, tret, varargs, LINKd);
3625
3626     type = type->semantic(loc, sc);
3627     assert(type->ty == Tfunction);
3628
3629     // Check that there is at least one argument of type size_t
3630     TypeFunction *tf = (TypeFunction *)type;
3631     if (Parameter::dim(tf->parameters) < 1)
3632     {
3633         error("at least one argument of type size_t expected");
3634     }
3635     else
3636     {
3637         Parameter *a = Parameter::getNth(tf->parameters, 0);
3638         if (!a->type->equals(Type::tsize_t))
3639             error("first argument must be type size_t, not %s", a->type->toChars());
3640     }
3641
3642     FuncDeclaration::semantic(sc);
3643 }
3644
3645 const char *NewDeclaration::kind()
3646 {
3647     return "allocator";
3648 }
3649
3650 int NewDeclaration::isVirtual()
3651 {
3652     return FALSE;
3653 }
3654
3655 int NewDeclaration::addPreInvariant()
3656 {
3657     return FALSE;
3658 }
3659
3660 int NewDeclaration::addPostInvariant()
3661 {
3662     return FALSE;
3663 }
3664
3665 void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3666 {
3667     buf->writestring("new");
3668     Parameter::argsToCBuffer(buf, hgs, arguments, varargs);
3669     bodyToCBuffer(buf, hgs);
3670 }
3671
3672
3673 /********************************* DeleteDeclaration ****************************/
3674
3675 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Parameters *arguments)
3676     : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
3677 {
3678     this->arguments = arguments;
3679 }
3680
3681 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
3682 {
3683     DeleteDeclaration *f;
3684
3685     f = new DeleteDeclaration(loc, endloc, NULL);
3686
3687     FuncDeclaration::syntaxCopy(f);
3688
3689     f->arguments = Parameter::arraySyntaxCopy(arguments);
3690
3691     return f;
3692 }
3693
3694
3695 void DeleteDeclaration::semantic(Scope *sc)
3696 {
3697     //printf("DeleteDeclaration::semantic()\n");
3698
3699     parent = sc->parent;
3700     Dsymbol *parent = toParent();
3701     ClassDeclaration *cd = parent->isClassDeclaration();
3702     if (!cd && !parent->isStructDeclaration())
3703     {
3704         error("new allocators only are for class or struct definitions");
3705     }
3706     if (!type)
3707         type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
3708
3709     type = type->semantic(loc, sc);
3710     assert(type->ty == Tfunction);
3711
3712     // Check that there is only one argument of type void*
3713     TypeFunction *tf = (TypeFunction *)type;
3714     if (Parameter::dim(tf->parameters) != 1)
3715     {
3716         error("one argument of type void* expected");
3717     }
3718     else
3719     {
3720         Parameter *a = Parameter::getNth(tf->parameters, 0);
3721         if (!a->type->equals(Type::tvoid->pointerTo()))
3722             error("one argument of type void* expected, not %s", a->type->toChars());
3723     }
3724
3725     FuncDeclaration::semantic(sc);
3726 }
3727
3728 const char *DeleteDeclaration::kind()
3729 {
3730     return "deallocator";
3731 }
3732
3733 int DeleteDeclaration::isDelete()
3734 {
3735     return TRUE;
3736 }
3737
3738 int DeleteDeclaration::isVirtual()
3739 {
3740     return FALSE;
3741 }
3742
3743 int DeleteDeclaration::addPreInvariant()
3744 {
3745     return FALSE;
3746 }
3747
3748 int DeleteDeclaration::addPostInvariant()
3749 {
3750     return FALSE;
3751 }
3752
3753 void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3754 {
3755     buf->writestring("delete");
3756     Parameter::argsToCBuffer(buf, hgs, arguments, 0);
3757     bodyToCBuffer(buf, hgs);
3758 }
Note: See TracBrowser for help on using the browser.