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