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