root/branches/dmdfe/func.c

Revision 740, 58.9 kB (checked in by Gregor, 1 year ago)

MERGE: DMD 1.019

Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2007 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <assert.h>
12
13 #include "mars.h"
14 #include "init.h"
15 #include "declaration.h"
16 #include "attrib.h"
17 #include "expression.h"
18 #include "scope.h"
19 #include "mtype.h"
20 #include "aggregate.h"
21 #include "identifier.h"
22 #include "id.h"
23 #include "module.h"
24 #include "statement.h"
25 #include "template.h"
26 #include "hdrgen.h"
27
28 #ifdef IN_GCC
29 #include "d-dmd-gcc.h"
30 #endif
31
32 /********************************* FuncDeclaration ****************************/
33
34 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
35     : Declaration(id)
36 {
37     this->storage_class = storage_class;
38     this->type = type;
39     this->loc = loc;
40     this->endloc = endloc;
41     fthrows = NULL;
42     frequire = NULL;
43     outId = NULL;
44     vresult = NULL;
45     returnLabel = NULL;
46     fensure = NULL;
47     fbody = NULL;
48     localsymtab = NULL;
49     vthis = NULL;
50     v_arguments = NULL;
51 #if IN_GCC
52     v_argptr = NULL;
53 #endif
54     parameters = NULL;
55     labtab = NULL;
56     overnext = NULL;
57     vtblIndex = -1;
58     hasReturnExp = 0;
59     naked = 0;
60     inlineStatus = ILSuninitialized;
61     inlineNest = 0;
62     inlineAsm = 0;
63     cantInterpret = 0;
64     semanticRun = 0;
65     nestedFrameRef = 0;
66     fes = NULL;
67     introducing = 0;
68     tintro = NULL;
69     inferRetType = (type && type->nextOf() == NULL);
70     scope = NULL;
71     hasReturnExp = 0;
72     nrvo_can = 1;
73     nrvo_var = NULL;
74     shidden = NULL;
75 }
76
77 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
78 {
79     FuncDeclaration *f;
80
81     //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
82     if (s)
83     f = (FuncDeclaration *)s;
84     else
85     f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
86     f->outId = outId;
87     f->frequire = frequire ? frequire->syntaxCopy() : NULL;
88     f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
89     f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
90     assert(!fthrows); // deprecated
91     return f;
92 }
93
94
95 // Do the semantic analysis on the external interface to the function.
96
97 void FuncDeclaration::semantic(Scope *sc)
98 {   TypeFunction *f;
99     StructDeclaration *sd;
100     ClassDeclaration *cd;
101     InterfaceDeclaration *id;
102
103 #if 0
104     printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
105     if (isFuncLiteralDeclaration())
106     printf("\tFuncLiteralDeclaration()\n");
107     printf("sc->parent = %s\n", sc->parent->toChars());
108     printf("type: %s\n", type->toChars());
109 #endif
110
111     if (type->nextOf())
112     type = type->semantic(loc, sc);
113     //type->print();
114     if (type->ty != Tfunction)
115     {
116     error("%s must be a function", toChars());
117     return;
118     }
119     f = (TypeFunction *)(type);
120     size_t nparams = Argument::dim(f->parameters);
121
122     linkage = sc->linkage;
123 //    if (!parent)
124     {
125     //parent = sc->scopesym;
126     parent = sc->parent;
127     }
128     protection = sc->protection;
129     storage_class |= sc->stc;
130     //printf("function storage_class = x%x\n", storage_class);
131     Dsymbol *parent = toParent();
132
133     if (isConst() || isAuto() || isScope())
134     error("functions cannot be const or auto");
135
136     if (isAbstract() && !isVirtual())
137     error("non-virtual functions cannot be abstract");
138 #if 0
139     if (isAbstract() && fbody)
140     error("abstract functions cannot have bodies");
141 #endif
142
143 #if 0
144     if (isStaticConstructor() || isStaticDestructor())
145     {
146     if (!isStatic() || type->nextOf()->ty != Tvoid)
147         error("static constructors / destructors must be static void");
148     if (f->arguments && f->arguments->dim)
149         error("static constructors / destructors must have empty parameter list");
150     // BUG: check for invalid storage classes
151     }
152 #endif
153
154 #ifdef IN_GCC
155     AggregateDeclaration *ad;
156
157     ad = parent->isAggregateDeclaration();
158     if (ad)
159     ad->methods.push(this);
160 #endif
161     sd = parent->isStructDeclaration();
162     if (sd)
163     {
164     // Verify no constructors, destructors, etc.
165     if (isCtorDeclaration() ||
166         isDtorDeclaration()
167         //|| isInvariantDeclaration()
168         //|| isUnitTestDeclaration()
169        )
170     {
171         error("special member functions not allowed for %ss", sd->kind());
172     }
173
174 #if 0
175     if (!sd->inv)
176         sd->inv = isInvariantDeclaration();
177
178     if (!sd->aggNew)
179         sd->aggNew = isNewDeclaration();
180
181     if (isDelete())
182     {
183         if (sd->aggDelete)
184         error("multiple delete's for struct %s", sd->toChars());
185         sd->aggDelete = (DeleteDeclaration *)(this);
186     }
187 #endif
188     }
189
190     id = parent->isInterfaceDeclaration();
191     if (id)
192     {
193     storage_class |= STCabstract;
194
195     if (isCtorDeclaration() ||
196         isDtorDeclaration() ||
197         isInvariantDeclaration() ||
198         isUnitTestDeclaration() || isNewDeclaration() || isDelete())
199         error("special function not allowed in interface %s", id->toChars());
200     if (fbody)
201         error("function body is not abstract in interface %s", id->toChars());
202     }
203
204     cd = parent->isClassDeclaration();
205     if (cd)
206     {   int vi;
207     CtorDeclaration *ctor;
208     DtorDeclaration *dtor;
209     InvariantDeclaration *inv;
210
211     if (isCtorDeclaration())
212     {
213 //      ctor = (CtorDeclaration *)this;
214 //      if (!cd->ctor)
215 //      cd->ctor = ctor;
216         return;
217     }
218
219 #if 0
220     dtor = isDtorDeclaration();
221     if (dtor)
222     {
223         if (cd->dtor)
224         error("multiple destructors for class %s", cd->toChars());
225         cd->dtor = dtor;
226     }
227
228     inv = isInvariantDeclaration();
229     if (inv)
230     {
231         cd->inv = inv;
232     }
233
234     if (isNewDeclaration())
235     {
236         if (!cd->aggNew)
237         cd->aggNew = (NewDeclaration *)(this);
238     }
239
240     if (isDelete())
241     {
242         if (cd->aggDelete)
243         error("multiple delete's for class %s", cd->toChars());
244         cd->aggDelete = (DeleteDeclaration *)(this);
245     }
246 #endif
247
248     if (storage_class & STCabstract)
249         cd->isabstract = 1;
250
251     // if static function, do not put in vtbl[]
252     if (!isVirtual())
253     {
254         //printf("\tnot virtual\n");
255         return;
256     }
257
258     // Find index of existing function in vtbl[] to override
259     if (cd->baseClass)
260     {
261         for (vi = 0; vi < cd->baseClass->vtbl.dim; vi++)
262         {
263         FuncDeclaration *fdv = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration();
264
265         // BUG: should give error if argument types match,
266         // but return type does not?
267
268         //printf("\tvtbl[%d] = '%s'\n", vi, fdv ? fdv->ident->toChars() : "");
269         if (fdv && fdv->ident == ident)
270         {
271             int cov = type->covariant(fdv->type);
272             //printf("\tbaseclass cov = %d\n", cov);
273             if (cov == 2)
274             {
275             //type->print();
276             //fdv->type->print();
277             //printf("%s %s\n", type->deco, fdv->type->deco);
278             error("of type %s overrides but is not covariant with %s of type %s",
279                 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
280             }
281             if (cov == 1)
282             {
283             if (fdv->isFinal())
284                 error("cannot override final function %s", fdv->toPrettyChars());
285             if (fdv->toParent() == parent)
286             {
287                 // If both are mixins, then error.
288                 // If either is not, the one that is not overrides
289                 // the other.
290                 if (fdv->parent->isClassDeclaration())
291                 goto L1;
292                 if (!this->parent->isClassDeclaration()
293 #if !BREAKABI
294                 && !isDtorDeclaration()
295 #endif
296                 )
297                 error("multiple overrides of same function");
298             }
299             cd->vtbl.data[vi] = (void *)this;
300             vtblIndex = vi;
301
302             /* This works by whenever this function is called,
303              * it actually returns tintro, which gets dynamically
304              * cast to type. But we know that tintro is a base
305              * of type, so we could optimize it by not doing a
306              * dynamic cast, but just subtracting the isBaseOf()
307              * offset if the value is != null.
308              */
309
310             if (fdv->tintro)
311                 tintro = fdv->tintro;
312             else if (!type->equals(fdv->type))
313             {
314                 /* Only need to have a tintro if the vptr
315                  * offsets differ
316                  */
317                 int offset;
318                 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
319                 {
320                 tintro = fdv->type;
321                 }
322             }
323             goto L1;
324             }
325             if (cov == 3)
326             {
327             cd->sizeok = 2; // can't finish due to forward reference
328             return;
329             }
330         }
331         }
332     }
333
334     // This is an 'introducing' function.
335
336     // Verify this doesn't override previous final function
337     if (cd->baseClass)
338     {   Dsymbol *s = cd->baseClass->search(loc, ident, 0);
339         if (s)
340         {
341         FuncDeclaration *f = s->isFuncDeclaration();
342         f = f->overloadExactMatch(type);
343         if (f && f->isFinal() && f->prot() != PROTprivate)
344             error("cannot override final function %s", f->toPrettyChars());
345         }
346     }
347
348     if (isFinal())
349     {
350         cd->vtblFinal.push(this);
351     }
352     else
353     {
354         // Append to end of vtbl[]
355         //printf("\tintroducing function\n");
356         introducing = 1;
357         vi = cd->vtbl.dim;
358         cd->vtbl.push(this);
359         vtblIndex = vi;
360     }
361
362     L1: ;
363
364     /* Go through all the interface bases.
365      * If this function is covariant with any members of those interface
366      * functions, set the tintro.
367      */
368     for (int i = 0; i < cd->interfaces_dim; i++)
369     {
370         BaseClass *b = cd->interfaces[i];
371         for (vi = 0; vi < b->base->vtbl.dim; vi++)
372         {
373         Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
374         //printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
375         FuncDeclaration *fdv = s->isFuncDeclaration();
376         if (fdv && fdv->ident == ident)
377         {
378             int cov = type->covariant(fdv->type);
379             //printf("\tcov = %d\n", cov);
380             if (cov == 2)
381             {
382             //type->print();
383             //fdv->type->print();
384             //printf("%s %s\n", type->deco, fdv->type->deco);
385             error("of type %s overrides but is not covariant with %s of type %s",
386                 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
387             }
388             if (cov == 1)
389             {   Type *ti = NULL;
390
391             if (fdv->tintro)
392                 ti = fdv->tintro;
393             else if (!type->equals(fdv->type))
394             {
395                 /* Only need to have a tintro if the vptr
396                  * offsets differ
397                  */
398                 int offset;
399                 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
400                 {
401                 ti = fdv->type;
402 #if 0
403                 if (offset)
404                     ti = fdv->type;
405                 else if (type->next->ty == Tclass)
406                 {   ClassDeclaration *cdn = ((TypeClass *)type->next)->sym;
407                     if (cdn && cdn->sizeok != 1)
408                     ti = fdv->type;
409                 }
410 #endif
411                 }
412             }
413             if (ti)
414             {
415                 if (tintro && !tintro->equals(ti))
416                 {
417                 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
418                 }
419                 tintro = ti;
420             }
421             goto L2;
422             }
423             if (cov == 3)
424             {
425             cd->sizeok = 2; // can't finish due to forward reference
426             return;
427             }
428         }
429         }
430     }
431
432     if (introducing && isOverride())
433     {
434         error("function %s does not override any", toChars());
435     }
436
437     L2: ;
438     }
439     else if (isOverride() && !parent->isTemplateInstance())
440     error("override only applies to class member functions");
441
442     /* Do not allow template instances to add virtual functions
443      * to a class.
444      */
445     if (isVirtual())
446     {
447     TemplateInstance *ti = parent->isTemplateInstance();
448     if (ti)
449     {
450         // Take care of nested templates
451         while (1)
452         {
453         TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
454         if (!ti2)
455             break;
456         ti = ti2;
457         }
458
459         // If it's a member template
460         ClassDeclaration *cd = ti->tempdecl->isClassMember();
461         if (cd)
462         {
463         error("cannot use template to add virtual function to class '%s'", cd->toChars());
464         }
465     }
466     }
467
468     if (isMain())
469     {
470     // Check parameters to see if they are either () or (char[][] args)
471     switch (nparams)
472     {
473         case 0:
474         break;
475
476         case 1:
477         {
478         Argument *arg0 = Argument::getNth(f->parameters, 0);
479         if (arg0->type->ty != Tarray ||
480             arg0->type->next->ty != Tarray ||
481             arg0->type->next->next->ty != Tchar ||
482             arg0->storageClass & (STCout | STCref | STClazy))
483             goto Lmainerr;
484         break;
485         }
486
487         default:
488         goto Lmainerr;
489     }
490
491     if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
492         error("must return int or void, not %s", f->nextOf()->toChars());
493     if (f->varargs)
494     {
495     Lmainerr:
496         error("parameters must be main() or main(char[][] args)");
497     }
498     }
499
500     if (ident == Id::assign && (sd || cd))
501     {   // Disallow identity assignment operator.
502
503     // opAssign(...)
504     if (nparams == 0)
505     {   if (f->varargs == 1)
506         goto Lassignerr;
507     }
508     else
509     {
510         Argument *arg0 = Argument::getNth(f->parameters, 0);
511         Type *t0 = arg0->type->toBasetype();
512         Type *tb = sd ? sd->type : cd->type;
513         if (arg0->type->implicitConvTo(tb) ||
514         (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
515            )
516         {
517         if (nparams == 1)
518             goto Lassignerr;
519         Argument *arg1 = Argument::getNth(f->parameters, 1);
520         if (arg1->defaultArg)
521             goto Lassignerr;
522         }
523     }
524     }
525
526     /* Save scope for possible later use (if we need the
527      * function internals)
528      */
529     scope = new Scope(*sc);
530     scope->setNoFree();
531     return;
532
533 Lassignerr:
534     error("identity assignment operator overload is illegal");
535 }
536
537 void FuncDeclaration::semantic2(Scope *sc)
538 {
539 }
540
541 // Do the semantic analysis on the internals of the function.
542
543 void FuncDeclaration::semantic3(Scope *sc)
544 {   TypeFunction *f;
545     AggregateDeclaration *ad;
546     VarDeclaration *argptr = NULL;
547     VarDeclaration *_arguments = NULL;
548
549     if (!parent)
550     {
551     printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
552     assert(0);
553     }
554     //printf("FuncDeclaration::semantic3('%s.%s', sc = %p)\n", parent->toChars(), toChars(), sc);
555     //fflush(stdout);
556     //{ static int x; if (++x == 2) *(char*)0=0; }
557     //printf("\tlinkage = %d\n", sc->linkage);
558
559     //printf(" sc->incontract = %d\n", sc->incontract);
560     if (semanticRun)
561     return;
562     semanticRun = 1;
563
564     if (!type || type->ty != Tfunction)
565     return;
566     f = (TypeFunction *)(type);
567     size_t nparams = Argument::dim(f->parameters);
568
569     // Check the 'throws' clause
570     if (fthrows)
571     {   int i;
572
573     for (i = 0; i < fthrows->dim; i++)
574     {
575         Type *t = (Type *)fthrows->data[i];
576
577         t = t->semantic(loc, sc);
578         if (!t->isClassHandle())
579         error("can only throw classes, not %s", t->toChars());
580     }
581     }
582
583     if (fbody || frequire)
584     {
585     // Establish function scope
586     ScopeDsymbol *ss;
587     Scope *sc2;
588
589     localsymtab = new DsymbolTable();
590
591     ss = new ScopeDsymbol();
592     ss->parent = sc->scopesym;
593     sc2 = sc->push(ss);
594     sc2->func = this;
595     sc2->parent = this;
596     sc2->callSuper = 0;
597     sc2->sbreak = NULL;
598     sc2->scontinue = NULL;
599     sc2->sw = NULL;
600     sc2->fes = fes;
601     sc2->linkage = LINKd;
602     sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated);
603     sc2->protection = PROTpublic;
604     sc2->explicitProtection = 0;
605     sc2->structalign = 8;
606     sc2->incontract = 0;
607     sc2->tf = NULL;
608     sc2->noctor = 0;
609
610     // Declare 'this'
611     ad = isThis();
612     if (ad)
613     {   VarDeclaration *v;
614
615         if (isFuncLiteralDeclaration() && isNested())
616         {
617         error("literals cannot be class members");
618         return;
619         }
620         else
621         {
622         assert(!isNested());    // can't be both member and nested
623         assert(ad->handle);
624         v = new ThisDeclaration(ad->handle);
625         v->storage_class |= STCparameter | STCin;
626         v->semantic(sc2);
627         if (!sc2->insert(v))
628             assert(0);
629         v->parent = this;
630         vthis = v;
631         }
632     }
633     else if (isNested())
634     {
635         VarDeclaration *v;
636
637         v = new ThisDeclaration(Type::tvoid->pointerTo());
638         v->storage_class |= STCparameter | STCin;
639         v->semantic(sc2);
640         if (!sc2->insert(v))
641         assert(0);
642         v->parent = this;
643         vthis = v;
644     }
645
646     // Declare hidden variable _arguments[] and _argptr
647     if (f->varargs == 1)
648     {   Type *t;
649
650         if (f->linkage == LINKd)
651         {   // Declare _arguments[]
652 #if BREAKABI
653         v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
654         v_arguments->storage_class = STCparameter | STCin;
655         v_arguments->semantic(sc2);
656         sc2->insert(v_arguments);
657         v_arguments->parent = this;
658
659         t = Type::typeinfo->type->arrayOf();
660         _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
661         _arguments->semantic(sc2);
662         sc2->insert(_arguments);
663         _arguments->parent = this;
664 #else
665         t = Type::typeinfo->type->arrayOf();
666         v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
667         v_arguments->storage_class = STCparameter | STCin;
668         v_arguments