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