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