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