Mercurial > projects > ldc
annotate dmd/expression.c @ 305:2b72433d5c8c trunk
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
Fixed problems with label collisions when using labels inside inline asm. LabelStatement is now easily reached given its
Identifier, which should be useful elsewhere too.
Enabled inline asm for building the lib/compiler/llvmdc runtime code, fixing branches out of asm makes this possible.
author | lindquist |
---|---|
date | Fri, 27 Jun 2008 22:04:35 +0200 |
parents | 297690b5d4a5 |
children | 7086a84ab3d6 |
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 <stdlib.h> | |
13 #include <ctype.h> | |
14 #include <assert.h> | |
15 #include <complex> | |
16 #include <math.h> | |
17 | |
18 #if _WIN32 && __DMC__ | |
19 extern "C" char * __cdecl __locale_decpoint; | |
20 #endif | |
21 | |
285
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
22 #if __MINGW32__ |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
23 #ifndef isnan |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
24 #define isnan _isnan |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
25 #endif |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
26 #endif |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
27 |
159 | 28 #if IN_GCC |
29 // Issues with using -include total.h (defines integer_t) and then complex.h fails... | |
30 #undef integer_t | |
31 #endif | |
32 | |
33 #ifdef __APPLE__ | |
34 #define integer_t dmd_integer_t | |
35 #endif | |
36 | |
37 #if IN_GCC || IN_LLVM | |
38 #include "mem.h" | |
39 #elif _WIN32 | |
40 #include "..\root\mem.h" | |
41 #elif linux | |
42 #include "../root/mem.h" | |
43 #endif | |
44 | |
45 //#include "port.h" | |
46 #include "mtype.h" | |
47 #include "init.h" | |
48 #include "expression.h" | |
49 #include "template.h" | |
50 #include "utf.h" | |
51 #include "enum.h" | |
52 #include "scope.h" | |
53 #include "statement.h" | |
54 #include "declaration.h" | |
55 #include "aggregate.h" | |
56 #include "import.h" | |
57 #include "id.h" | |
58 #include "dsymbol.h" | |
59 #include "module.h" | |
60 #include "attrib.h" | |
61 #include "hdrgen.h" | |
62 #include "parse.h" | |
63 | |
64 Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim); | |
65 | |
66 #define LOGSEMANTIC 0 | |
67 | |
68 /********************************** | |
69 * Set operator precedence for each operator. | |
70 */ | |
71 | |
72 // Operator precedence - greater values are higher precedence | |
73 | |
74 enum PREC | |
75 { | |
76 PREC_zero, | |
77 PREC_expr, | |
78 PREC_assign, | |
79 PREC_cond, | |
80 PREC_oror, | |
81 PREC_andand, | |
82 PREC_or, | |
83 PREC_xor, | |
84 PREC_and, | |
85 PREC_equal, | |
86 PREC_rel, | |
87 PREC_shift, | |
88 PREC_add, | |
89 PREC_mul, | |
90 PREC_unary, | |
91 PREC_primary, | |
92 }; | |
93 | |
94 enum PREC precedence[TOKMAX]; | |
95 | |
96 void initPrecedence() | |
97 { | |
98 precedence[TOKdotvar] = PREC_primary; | |
99 precedence[TOKimport] = PREC_primary; | |
100 precedence[TOKidentifier] = PREC_primary; | |
101 precedence[TOKthis] = PREC_primary; | |
102 precedence[TOKsuper] = PREC_primary; | |
103 precedence[TOKint64] = PREC_primary; | |
104 precedence[TOKfloat64] = PREC_primary; | |
105 precedence[TOKnull] = PREC_primary; | |
106 precedence[TOKstring] = PREC_primary; | |
107 precedence[TOKarrayliteral] = PREC_primary; | |
108 precedence[TOKtypedot] = PREC_primary; | |
109 precedence[TOKtypeid] = PREC_primary; | |
110 precedence[TOKis] = PREC_primary; | |
111 precedence[TOKassert] = PREC_primary; | |
112 precedence[TOKfunction] = PREC_primary; | |
113 precedence[TOKvar] = PREC_primary; | |
114 | |
115 // post | |
116 precedence[TOKdotti] = PREC_primary; | |
117 precedence[TOKdot] = PREC_primary; | |
118 // precedence[TOKarrow] = PREC_primary; | |
119 precedence[TOKplusplus] = PREC_primary; | |
120 precedence[TOKminusminus] = PREC_primary; | |
121 precedence[TOKcall] = PREC_primary; | |
122 precedence[TOKslice] = PREC_primary; | |
123 precedence[TOKarray] = PREC_primary; | |
124 | |
125 precedence[TOKaddress] = PREC_unary; | |
126 precedence[TOKstar] = PREC_unary; | |
127 precedence[TOKneg] = PREC_unary; | |
128 precedence[TOKuadd] = PREC_unary; | |
129 precedence[TOKnot] = PREC_unary; | |
130 precedence[TOKtobool] = PREC_add; | |
131 precedence[TOKtilde] = PREC_unary; | |
132 precedence[TOKdelete] = PREC_unary; | |
133 precedence[TOKnew] = PREC_unary; | |
134 precedence[TOKcast] = PREC_unary; | |
135 | |
136 precedence[TOKmul] = PREC_mul; | |
137 precedence[TOKdiv] = PREC_mul; | |
138 precedence[TOKmod] = PREC_mul; | |
139 | |
140 precedence[TOKadd] = PREC_add; | |
141 precedence[TOKmin] = PREC_add; | |
142 precedence[TOKcat] = PREC_add; | |
143 | |
144 precedence[TOKshl] = PREC_shift; | |
145 precedence[TOKshr] = PREC_shift; | |
146 precedence[TOKushr] = PREC_shift; | |
147 | |
148 precedence[TOKlt] = PREC_rel; | |
149 precedence[TOKle] = PREC_rel; | |
150 precedence[TOKgt] = PREC_rel; | |
151 precedence[TOKge] = PREC_rel; | |
152 precedence[TOKunord] = PREC_rel; | |
153 precedence[TOKlg] = PREC_rel; | |
154 precedence[TOKleg] = PREC_rel; | |
155 precedence[TOKule] = PREC_rel; | |
156 precedence[TOKul] = PREC_rel; | |
157 precedence[TOKuge] = PREC_rel; | |
158 precedence[TOKug] = PREC_rel; | |
159 precedence[TOKue] = PREC_rel; | |
160 precedence[TOKin] = PREC_rel; | |
161 | |
162 precedence[TOKequal] = PREC_equal; | |
163 precedence[TOKnotequal] = PREC_equal; | |
164 precedence[TOKidentity] = PREC_equal; | |
165 precedence[TOKnotidentity] = PREC_equal; | |
166 | |
167 precedence[TOKand] = PREC_and; | |
168 | |
169 precedence[TOKxor] = PREC_xor; | |
170 | |
171 precedence[TOKor] = PREC_or; | |
172 | |
173 precedence[TOKandand] = PREC_andand; | |
174 | |
175 precedence[TOKoror] = PREC_oror; | |
176 | |
177 precedence[TOKquestion] = PREC_cond; | |
178 | |
179 precedence[TOKassign] = PREC_assign; | |
180 precedence[TOKconstruct] = PREC_assign; | |
181 precedence[TOKblit] = PREC_assign; | |
182 precedence[TOKaddass] = PREC_assign; | |
183 precedence[TOKminass] = PREC_assign; | |
184 precedence[TOKcatass] = PREC_assign; | |
185 precedence[TOKmulass] = PREC_assign; | |
186 precedence[TOKdivass] = PREC_assign; | |
187 precedence[TOKmodass] = PREC_assign; | |
188 precedence[TOKshlass] = PREC_assign; | |
189 precedence[TOKshrass] = PREC_assign; | |
190 precedence[TOKushrass] = PREC_assign; | |
191 precedence[TOKandass] = PREC_assign; | |
192 precedence[TOKorass] = PREC_assign; | |
193 precedence[TOKxorass] = PREC_assign; | |
194 | |
195 precedence[TOKcomma] = PREC_expr; | |
196 } | |
197 | |
198 /***************************************** | |
199 * Determine if 'this' is available. | |
200 * If it is, return the FuncDeclaration that has it. | |
201 */ | |
202 | |
203 FuncDeclaration *hasThis(Scope *sc) | |
204 { FuncDeclaration *fd; | |
205 FuncDeclaration *fdthis; | |
206 | |
207 //printf("hasThis()\n"); | |
208 fdthis = sc->parent->isFuncDeclaration(); | |
209 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); | |
210 | |
211 // Go upwards until we find the enclosing member function | |
212 fd = fdthis; | |
213 while (1) | |
214 { | |
215 if (!fd) | |
216 { | |
217 goto Lno; | |
218 } | |
219 if (!fd->isNested()) | |
220 break; | |
221 | |
222 Dsymbol *parent = fd->parent; | |
223 while (parent) | |
224 { | |
225 TemplateInstance *ti = parent->isTemplateInstance(); | |
226 if (ti) | |
227 parent = ti->parent; | |
228 else | |
229 break; | |
230 } | |
231 | |
232 fd = fd->parent->isFuncDeclaration(); | |
233 } | |
234 | |
235 if (!fd->isThis()) | |
236 { //printf("test '%s'\n", fd->toChars()); | |
237 goto Lno; | |
238 } | |
239 | |
240 assert(fd->vthis); | |
241 return fd; | |
242 | |
243 Lno: | |
244 return NULL; // don't have 'this' available | |
245 } | |
246 | |
247 | |
248 /*************************************** | |
249 * Pull out any properties. | |
250 */ | |
251 | |
252 Expression *resolveProperties(Scope *sc, Expression *e) | |
253 { | |
254 //printf("resolveProperties(%s)\n", e->toChars()); | |
255 if (e->type) | |
256 { | |
257 Type *t = e->type->toBasetype(); | |
258 | |
259 if (t->ty == Tfunction) | |
260 { | |
261 e = new CallExp(e->loc, e); | |
262 e = e->semantic(sc); | |
263 } | |
264 | |
265 /* Look for e being a lazy parameter; rewrite as delegate call | |
266 */ | |
267 else if (e->op == TOKvar) | |
268 { VarExp *ve = (VarExp *)e; | |
269 | |
270 if (ve->var->storage_class & STClazy) | |
271 { | |
272 e = new CallExp(e->loc, e); | |
273 e = e->semantic(sc); | |
274 } | |
275 } | |
276 | |
277 else if (e->op == TOKdotexp) | |
278 { | |
279 e->error("expression has no value"); | |
280 } | |
281 } | |
282 return e; | |
283 } | |
284 | |
285 /****************************** | |
286 * Perform semantic() on an array of Expressions. | |
287 */ | |
288 | |
289 void arrayExpressionSemantic(Expressions *exps, Scope *sc) | |
290 { | |
291 if (exps) | |
292 { | |
293 for (size_t i = 0; i < exps->dim; i++) | |
294 { Expression *e = (Expression *)exps->data[i]; | |
295 | |
296 e = e->semantic(sc); | |
297 exps->data[i] = (void *)e; | |
298 } | |
299 } | |
300 } | |
301 | |
302 /**************************************** | |
303 * Expand tuples. | |
304 */ | |
305 | |
306 void expandTuples(Expressions *exps) | |
307 { | |
308 //printf("expandTuples()\n"); | |
309 if (exps) | |
310 { | |
311 for (size_t i = 0; i < exps->dim; i++) | |
312 { Expression *arg = (Expression *)exps->data[i]; | |
313 if (!arg) | |
314 continue; | |
315 | |
316 // Look for tuple with 0 members | |
317 if (arg->op == TOKtype) | |
318 { TypeExp *e = (TypeExp *)arg; | |
319 if (e->type->toBasetype()->ty == Ttuple) | |
320 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype(); | |
321 | |
322 if (!tt->arguments || tt->arguments->dim == 0) | |
323 { | |
324 exps->remove(i); | |
325 if (i == exps->dim) | |
326 return; | |
327 i--; | |
328 continue; | |
329 } | |
330 } | |
331 } | |
332 | |
333 // Inline expand all the tuples | |
334 while (arg->op == TOKtuple) | |
335 { TupleExp *te = (TupleExp *)arg; | |
336 | |
337 exps->remove(i); // remove arg | |
338 exps->insert(i, te->exps); // replace with tuple contents | |
339 if (i == exps->dim) | |
340 return; // empty tuple, no more arguments | |
341 arg = (Expression *)exps->data[i]; | |
342 } | |
343 } | |
344 } | |
345 } | |
346 | |
347 /**************************************** | |
348 * Preprocess arguments to function. | |
349 */ | |
350 | |
351 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps) | |
352 { | |
353 if (exps) | |
354 { | |
355 expandTuples(exps); | |
356 | |
357 for (size_t i = 0; i < exps->dim; i++) | |
358 { Expression *arg = (Expression *)exps->data[i]; | |
359 | |
360 if (!arg->type) | |
361 { | |
362 #ifdef DEBUG | |
363 if (!global.gag) | |
364 printf("1: \n"); | |
365 #endif | |
366 arg->error("%s is not an expression", arg->toChars()); | |
367 arg = new IntegerExp(arg->loc, 0, Type::tint32); | |
368 } | |
369 | |
370 arg = resolveProperties(sc, arg); | |
371 exps->data[i] = (void *) arg; | |
372 | |
373 //arg->rvalue(); | |
374 #if 0 | |
375 if (arg->type->ty == Tfunction) | |
376 { | |
377 arg = new AddrExp(arg->loc, arg); | |
378 arg = arg->semantic(sc); | |
379 exps->data[i] = (void *) arg; | |
380 } | |
381 #endif | |
382 } | |
383 } | |
384 } | |
385 | |
386 | |
387 /**************************************** | |
388 * Now that we know the exact type of the function we're calling, | |
389 * the arguments[] need to be adjusted: | |
390 * 1) implicitly convert argument to the corresponding parameter type | |
391 * 2) add default arguments for any missing arguments | |
392 * 3) do default promotions on arguments corresponding to ... | |
393 * 4) add hidden _arguments[] argument | |
394 */ | |
395 | |
396 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments) | |
397 { | |
398 unsigned n; | |
399 int done; | |
400 Type *tb; | |
401 | |
402 //printf("functionArguments()\n"); | |
403 assert(arguments); | |
404 size_t nargs = arguments ? arguments->dim : 0; | |
405 size_t nparams = Argument::dim(tf->parameters); | |
406 | |
407 if (nargs > nparams && tf->varargs == 0) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
408 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 409 |
410 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) | |
411 | |
412 done = 0; | |
413 for (size_t i = 0; i < n; i++) | |
414 { | |
415 Expression *arg; | |
416 | |
417 if (i < nargs) | |
418 arg = (Expression *)arguments->data[i]; | |
419 else | |
420 arg = NULL; | |
421 | |
422 if (i < nparams) | |
423 { | |
424 Argument *p = Argument::getNth(tf->parameters, i); | |
425 | |
426 if (!arg) | |
427 { | |
428 if (!p->defaultArg) | |
429 { | |
430 if (tf->varargs == 2 && i + 1 == nparams) | |
431 goto L2; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
432 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 433 break; |
434 } | |
435 arg = p->defaultArg->copy(); | |
436 arguments->push(arg); | |
437 nargs++; | |
438 } | |
439 | |
440 if (tf->varargs == 2 && i + 1 == nparams) | |
441 { | |
442 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); | |
443 if (arg->implicitConvTo(p->type)) | |
444 { | |
445 if (nargs != nparams) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
446 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 447 goto L1; |
448 } | |
449 L2: | |
450 Type *tb = p->type->toBasetype(); | |
451 Type *tret = p->isLazyArray(); | |
452 switch (tb->ty) | |
453 { | |
454 case Tsarray: | |
455 case Tarray: | |
456 { // Create a static array variable v of type arg->type | |
457 #ifdef IN_GCC | |
458 /* GCC 4.0 does not like zero length arrays used like | |
459 this; pass a null array value instead. Could also | |
460 just make a one-element array. */ | |
461 if (nargs - i == 0) | |
462 { | |
463 arg = new NullExp(loc); | |
464 break; | |
465 } | |
466 #endif | |
467 static int idn; | |
468 char name[10 + sizeof(idn)*3 + 1]; | |
469 sprintf(name, "__arrayArg%d", ++idn); | |
470 Identifier *id = Lexer::idPool(name); | |
471 Type *t = new TypeSArray(tb->next, new IntegerExp(nargs - i)); | |
472 t = t->semantic(loc, sc); | |
473 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); | |
474 v->semantic(sc); | |
475 v->parent = sc->parent; | |
476 //sc->insert(v); | |
477 | |
478 Expression *c = new DeclarationExp(0, v); | |
479 c->type = v->type; | |
480 | |
481 for (size_t u = i; u < nargs; u++) | |
482 { Expression *a = (Expression *)arguments->data[u]; | |
483 if (tret && !tb->next->equals(a->type)) | |
484 a = a->toDelegate(sc, tret); | |
485 | |
486 Expression *e = new VarExp(loc, v); | |
487 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); | |
488 e = new AssignExp(loc, e, a); | |
489 if (c) | |
490 c = new CommaExp(loc, c, e); | |
491 else | |
492 c = e; | |
493 } | |
494 arg = new VarExp(loc, v); | |
495 if (c) | |
496 arg = new CommaExp(loc, c, arg); | |
497 break; | |
498 } | |
499 case Tclass: | |
500 { /* Set arg to be: | |
501 * new Tclass(arg0, arg1, ..., argn) | |
502 */ | |
503 Expressions *args = new Expressions(); | |
504 args->setDim(nargs - i); | |
505 for (size_t u = i; u < nargs; u++) | |
506 args->data[u - i] = arguments->data[u]; | |
507 arg = new NewExp(loc, NULL, NULL, p->type, args); | |
508 break; | |
509 } | |
510 default: | |
511 if (!arg) | |
512 { error(loc, "not enough arguments"); | |
513 return; | |
514 } | |
515 break; | |
516 } | |
517 arg = arg->semantic(sc); | |
518 //printf("\targ = '%s'\n", arg->toChars()); | |
519 arguments->setDim(i + 1); | |
520 done = 1; | |
521 } | |
522 | |
523 L1: | |
524 if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) | |
525 arg = arg->implicitCastTo(sc, p->type); | |
526 if (p->storageClass & (STCout | STCref)) | |
527 { | |
528 // BUG: should check that argument to ref is type 'invariant' | |
529 // BUG: assignments to ref should also be type 'invariant' | |
530 arg = arg->modifiableLvalue(sc, arg); | |
531 | |
532 //if (arg->op == TOKslice) | |
533 //arg->error("cannot modify slice %s", arg->toChars()); | |
534 } | |
535 | |
536 // Convert static arrays to pointers | |
537 tb = arg->type->toBasetype(); | |
538 if (tb->ty == Tsarray) | |
539 { | |
540 arg = arg->checkToPointer(); | |
541 } | |
542 | |
543 // Convert lazy argument to a delegate | |
544 if (p->storageClass & STClazy) | |
545 { | |
546 arg = arg->toDelegate(sc, p->type); | |
547 } | |
548 } | |
549 else | |
550 { | |
551 | |
552 // If not D linkage, do promotions | |
553 if (tf->linkage != LINKd) | |
554 { | |
555 // Promote bytes, words, etc., to ints | |
556 arg = arg->integralPromotions(sc); | |
557 | |
558 // Promote floats to doubles | |
559 switch (arg->type->ty) | |
560 { | |
561 case Tfloat32: | |
562 arg = arg->castTo(sc, Type::tfloat64); | |
563 break; | |
564 | |
565 case Timaginary32: | |
566 arg = arg->castTo(sc, Type::timaginary64); | |
567 break; | |
568 } | |
569 } | |
570 | |
571 // Convert static arrays to dynamic arrays | |
572 tb = arg->type->toBasetype(); | |
573 if (tb->ty == Tsarray) | |
574 { TypeSArray *ts = (TypeSArray *)tb; | |
575 Type *ta = tb->next->arrayOf(); | |
576 if (ts->size(arg->loc) == 0) | |
577 { arg = new NullExp(arg->loc); | |
578 arg->type = ta; | |
579 } | |
580 else | |
581 arg = arg->castTo(sc, ta); | |
582 } | |
583 | |
584 arg->rvalue(); | |
585 } | |
586 arg = arg->optimize(WANTvalue); | |
587 arguments->data[i] = (void *) arg; | |
588 if (done) | |
589 break; | |
590 } | |
591 | |
592 #if !IN_LLVM | |
593 // If D linkage and variadic, add _arguments[] as first argument | |
594 if (tf->linkage == LINKd && tf->varargs == 1) | |
595 { | |
596 Expression *e; | |
597 | |
598 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams], | |
599 arguments->dim - nparams); | |
600 arguments->insert(0, e); | |
601 } | |
602 #endif | |
603 } | |
604 | |
605 /************************************************** | |
606 * Write expression out to buf, but wrap it | |
607 * in ( ) if its precedence is less than pr. | |
608 */ | |
609 | |
610 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr) | |
611 { | |
612 if (precedence[e->op] < pr) | |
613 { | |
614 buf->writeByte('('); | |
615 e->toCBuffer(buf, hgs); | |
616 buf->writeByte(')'); | |
617 } | |
618 else | |
619 e->toCBuffer(buf, hgs); | |
620 } | |
621 | |
622 /************************************************** | |
623 * Write out argument list to buf. | |
624 */ | |
625 | |
626 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
627 { | |
628 if (arguments) | |
629 { | |
630 for (size_t i = 0; i < arguments->dim; i++) | |
631 { Expression *arg = (Expression *)arguments->data[i]; | |
632 | |
633 if (arg) | |
634 { if (i) | |
635 buf->writeByte(','); | |
636 expToCBuffer(buf, hgs, arg, PREC_assign); | |
637 } | |
638 } | |
639 } | |
640 } | |
641 | |
642 /************************************************** | |
643 * Write out argument types to buf. | |
644 */ | |
645 | |
646 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
647 { | |
648 if (arguments) | |
649 { OutBuffer argbuf; | |
650 | |
651 for (size_t i = 0; i < arguments->dim; i++) | |
652 { Expression *arg = (Expression *)arguments->data[i]; | |
653 | |
654 if (i) | |
655 buf->writeByte(','); | |
656 argbuf.reset(); | |
657 arg->type->toCBuffer2(&argbuf, hgs, 0); | |
658 buf->write(&argbuf); | |
659 } | |
660 } | |
661 } | |
662 | |
663 /******************************** Expression **************************/ | |
664 | |
665 Expression::Expression(Loc loc, enum TOK op, int size) | |
666 : loc(loc) | |
667 { | |
668 this->loc = loc; | |
669 this->op = op; | |
670 this->size = size; | |
671 type = NULL; | |
672 } | |
673 | |
674 Expression *Expression::syntaxCopy() | |
675 { | |
676 //printf("Expression::syntaxCopy()\n"); | |
677 //dump(0); | |
678 return copy(); | |
679 } | |
680 | |
681 /********************************* | |
682 * Does *not* do a deep copy. | |
683 */ | |
684 | |
685 Expression *Expression::copy() | |
686 { | |
687 Expression *e; | |
688 if (!size) | |
689 { | |
690 #ifdef DEBUG | |
691 fprintf(stdmsg, "No expression copy for: %s\n", toChars()); | |
692 printf("op = %d\n", op); | |
693 dump(0); | |
694 #endif | |
695 assert(0); | |
696 } | |
697 e = (Expression *)mem.malloc(size); | |
698 return (Expression *)memcpy(e, this, size); | |
699 } | |
700 | |
701 /************************** | |
702 * Semantically analyze Expression. | |
703 * Determine types, fold constants, etc. | |
704 */ | |
705 | |
706 Expression *Expression::semantic(Scope *sc) | |
707 { | |
708 #if LOGSEMANTIC | |
709 printf("Expression::semantic()\n"); | |
710 #endif | |
711 if (type) | |
712 type = type->semantic(loc, sc); | |
713 else | |
714 type = Type::tvoid; | |
715 return this; | |
716 } | |
717 | |
718 void Expression::print() | |
719 { | |
720 fprintf(stdmsg, "%s\n", toChars()); | |
721 fflush(stdmsg); | |
722 } | |
723 | |
724 char *Expression::toChars() | |
725 { OutBuffer *buf; | |
726 HdrGenState hgs; | |
727 | |
728 memset(&hgs, 0, sizeof(hgs)); | |
729 buf = new OutBuffer(); | |
730 toCBuffer(buf, &hgs); | |
731 return buf->toChars(); | |
732 } | |
733 | |
734 void Expression::error(const char *format, ...) | |
735 { | |
736 va_list ap; | |
737 va_start(ap, format); | |
738 ::verror(loc, format, ap); | |
739 va_end( ap ); | |
740 } | |
741 | |
742 void Expression::rvalue() | |
743 { | |
744 if (type && type->toBasetype()->ty == Tvoid) | |
745 { error("expression %s is void and has no value", toChars()); | |
746 #if 0 | |
747 dump(0); | |
748 halt(); | |
749 #endif | |
750 } | |
751 } | |
752 | |
753 Expression *Expression::combine(Expression *e1, Expression *e2) | |
754 { | |
755 if (e1) | |
756 { | |
757 if (e2) | |
758 { | |
759 e1 = new CommaExp(e1->loc, e1, e2); | |
760 e1->type = e2->type; | |
761 } | |
762 } | |
763 else | |
764 e1 = e2; | |
765 return e1; | |
766 } | |
767 | |
768 integer_t Expression::toInteger() | |
769 { | |
770 //printf("Expression %s\n", Token::toChars(op)); | |
771 error("Integer constant expression expected instead of %s", toChars()); | |
772 return 0; | |
773 } | |
774 | |
775 uinteger_t Expression::toUInteger() | |
776 { | |
777 //printf("Expression %s\n", Token::toChars(op)); | |
778 return (uinteger_t)toInteger(); | |
779 } | |
780 | |
781 real_t Expression::toReal() | |
782 { | |
783 error("Floating point constant expression expected instead of %s", toChars()); | |
784 return 0; | |
785 } | |
786 | |
787 real_t Expression::toImaginary() | |
788 { | |
789 error("Floating point constant expression expected instead of %s", toChars()); | |
790 return 0; | |
791 } | |
792 | |
793 complex_t Expression::toComplex() | |
794 { | |
795 error("Floating point constant expression expected instead of %s", toChars()); | |
796 #ifdef IN_GCC | |
797 return complex_t(real_t(0)); // %% nicer | |
798 #else | |
799 return 0; | |
800 #endif | |
801 } | |
802 | |
803 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
804 { | |
805 buf->writestring(Token::toChars(op)); | |
806 } | |
807 | |
808 void Expression::toMangleBuffer(OutBuffer *buf) | |
809 { | |
810 error("expression %s is not a valid template value argument", toChars()); | |
811 } | |
812 | |
813 /******************************* | |
814 * Give error if we're not an lvalue. | |
815 * If we can, convert expression to be an lvalue. | |
816 */ | |
817 | |
818 Expression *Expression::toLvalue(Scope *sc, Expression *e) | |
819 { | |
820 if (!e) | |
821 e = this; | |
822 else if (!loc.filename) | |
823 loc = e->loc; | |
824 error("%s is not an lvalue", e->toChars()); | |
825 return this; | |
826 } | |
827 | |
828 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) | |
829 { | |
830 // See if this expression is a modifiable lvalue (i.e. not const) | |
831 return toLvalue(sc, e); | |
832 } | |
833 | |
834 /************************************ | |
835 * Detect cases where pointers to the stack can 'escape' the | |
836 * lifetime of the stack frame. | |
837 */ | |
838 | |
839 void Expression::checkEscape() | |
840 { | |
841 } | |
842 | |
843 void Expression::checkScalar() | |
844 { | |
845 if (!type->isscalar()) | |
846 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); | |
847 } | |
848 | |
849 void Expression::checkNoBool() | |
850 { | |
851 if (type->toBasetype()->ty == Tbool) | |
852 error("operation not allowed on bool '%s'", toChars()); | |
853 } | |
854 | |
855 Expression *Expression::checkIntegral() | |
856 { | |
857 if (!type->isintegral()) | |
858 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); | |
859 return new IntegerExp(0); | |
860 } | |
861 return this; | |
862 } | |
863 | |
864 Expression *Expression::checkArithmetic() | |
865 { | |
866 if (!type->isintegral() && !type->isfloating()) | |
867 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); | |
868 return new IntegerExp(0); | |
869 } | |
870 return this; | |
871 } | |
872 | |
873 void Expression::checkDeprecated(Scope *sc, Dsymbol *s) | |
874 { | |
875 s->checkDeprecated(loc, sc); | |
876 } | |
877 | |
878 /******************************** | |
879 * Check for expressions that have no use. | |
880 * Input: | |
881 * flag 0 not going to use the result, so issue error message if no | |
882 * side effects | |
883 * 1 the result of the expression is used, but still check | |
884 * for useless subexpressions | |
885 * 2 do not issue error messages, just return !=0 if expression | |
886 * has side effects | |
887 */ | |
888 | |
889 int Expression::checkSideEffect(int flag) | |
890 { | |
891 if (flag == 0) | |
892 { if (op == TOKimport) | |
893 { | |
894 error("%s has no effect", toChars()); | |
895 } | |
896 else | |
897 error("%s has no effect in expression (%s)", | |
898 Token::toChars(op), toChars()); | |
899 } | |
900 return 0; | |
901 } | |
902 | |
903 /***************************** | |
904 * Check that expression can be tested for true or false. | |
905 */ | |
906 | |
907 Expression *Expression::checkToBoolean() | |
908 { | |
909 // Default is 'yes' - do nothing | |
910 | |
911 #ifdef DEBUG | |
912 if (!type) | |
913 dump(0); | |
914 #endif | |
915 | |
916 if (!type->checkBoolean()) | |
917 { | |
918 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars()); | |
919 } | |
920 return this; | |
921 } | |
922 | |
923 /**************************** | |
924 */ | |
925 | |
926 Expression *Expression::checkToPointer() | |
927 { | |
928 Expression *e; | |
929 Type *tb; | |
930 | |
931 //printf("Expression::checkToPointer()\n"); | |
932 e = this; | |
933 | |
934 // If C static array, convert to pointer | |
935 tb = type->toBasetype(); | |
936 if (tb->ty == Tsarray) | |
937 { TypeSArray *ts = (TypeSArray *)tb; | |
938 if (ts->size(loc) == 0) | |
939 e = new NullExp(loc); | |
940 else | |
941 e = new AddrExp(loc, this); | |
942 e->type = tb->next->pointerTo(); | |
943 } | |
944 return e; | |
945 } | |
946 | |
947 /****************************** | |
948 * Take address of expression. | |
949 */ | |
950 | |
951 Expression *Expression::addressOf(Scope *sc) | |
952 { | |
953 Expression *e; | |
954 | |
955 //printf("Expression::addressOf()\n"); | |
956 e = toLvalue(sc, NULL); | |
957 e = new AddrExp(loc, e); | |
958 e->type = type->pointerTo(); | |
959 return e; | |
960 } | |
961 | |
962 /****************************** | |
963 * If this is a reference, dereference it. | |
964 */ | |
965 | |
966 Expression *Expression::deref() | |
967 { | |
968 //printf("Expression::deref()\n"); | |
969 if (type->ty == Treference) | |
970 { Expression *e; | |
971 | |
972 e = new PtrExp(loc, this); | |
973 e->type = type->next; | |
974 return e; | |
975 } | |
976 return this; | |
977 } | |
978 | |
979 /******************************** | |
980 * Does this expression statically evaluate to a boolean TRUE or FALSE? | |
981 */ | |
982 | |
983 int Expression::isBool(int result) | |
984 { | |
985 return FALSE; | |
986 } | |
987 | |
988 /******************************** | |
989 * Does this expression result in either a 1 or a 0? | |
990 */ | |
991 | |
992 int Expression::isBit() | |
993 { | |
994 return FALSE; | |
995 } | |
996 | |
997 Expressions *Expression::arraySyntaxCopy(Expressions *exps) | |
998 { Expressions *a = NULL; | |
999 | |
1000 if (exps) | |
1001 { | |
1002 a = new Expressions(); | |
1003 a->setDim(exps->dim); | |
1004 for (int i = 0; i < a->dim; i++) | |
1005 { Expression *e = (Expression *)exps->data[i]; | |
1006 | |
1007 e = e->syntaxCopy(); | |
1008 a->data[i] = e; | |
1009 } | |
1010 } | |
1011 return a; | |
1012 } | |
1013 | |
1014 /******************************** IntegerExp **************************/ | |
1015 | |
1016 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type) | |
1017 : Expression(loc, TOKint64, sizeof(IntegerExp)) | |
1018 { | |
1019 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : ""); | |
1020 if (type && !type->isscalar()) | |
1021 { | |
1022 error("integral constant must be scalar type, not %s", type->toChars()); | |
1023 type = Type::terror; | |
1024 } | |
1025 this->type = type; | |
1026 this->value = value; | |
1027 } | |
1028 | |
1029 IntegerExp::IntegerExp(integer_t value) | |
1030 : Expression(0, TOKint64, sizeof(IntegerExp)) | |
1031 { | |
1032 this->type = Type::tint32; | |
1033 this->value = value; | |
1034 } | |
1035 | |
1036 int IntegerExp::equals(Object *o) | |
1037 { IntegerExp *ne; | |
1038 | |
1039 if (this == o || | |
1040 (((Expression *)o)->op == TOKint64 && | |
1041 ((ne = (IntegerExp *)o), type->equals(ne->type)) && | |
1042 value == ne->value)) | |
1043 return 1; | |
1044 return 0; | |
1045 } | |
1046 | |
1047 char *IntegerExp::toChars() | |
1048 { | |
1049 #if 1 | |
1050 return Expression::toChars(); | |
1051 #else | |
1052 static char buffer[sizeof(value) * 3 + 1]; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1053 sprintf(buffer, "%lld", value); |
159 | 1054 return buffer; |
1055 #endif | |
1056 } | |
1057 | |
1058 integer_t IntegerExp::toInteger() | |
1059 { Type *t; | |
1060 | |
1061 t = type; | |
1062 while (t) | |
1063 { | |
1064 switch (t->ty) | |
1065 { | |
1066 case Tbit: | |
1067 case Tbool: value = (value != 0); break; | |
1068 case Tint8: value = (d_int8) value; break; | |
1069 case Tchar: | |
1070 case Tuns8: value = (d_uns8) value; break; | |
1071 case Tint16: value = (d_int16) value; break; | |
1072 case Twchar: | |
1073 case Tuns16: value = (d_uns16) value; break; | |
1074 case Tint32: value = (d_int32) value; break; | |
1075 case Tpointer: | |
1076 case Tdchar: | |
1077 case Tuns32: value = (d_uns32) value; break; | |
1078 case Tint64: value = (d_int64) value; break; | |
1079 case Tuns64: value = (d_uns64) value; break; | |
1080 | |
1081 case Tenum: | |
1082 { | |
1083 TypeEnum *te = (TypeEnum *)t; | |
1084 t = te->sym->memtype; | |
1085 continue; | |
1086 } | |
1087 | |
1088 case Ttypedef: | |
1089 { | |
1090 TypeTypedef *tt = (TypeTypedef *)t; | |
1091 t = tt->sym->basetype; | |
1092 continue; | |
1093 } | |
1094 | |
1095 default: | |
1096 print(); | |
1097 type->print(); | |
1098 assert(0); | |
1099 break; | |
1100 } | |
1101 break; | |
1102 } | |
1103 return value; | |
1104 } | |
1105 | |
1106 real_t IntegerExp::toReal() | |
1107 { | |
1108 Type *t; | |
1109 | |
1110 toInteger(); | |
1111 t = type->toBasetype(); | |
1112 if (t->ty == Tuns64) | |
1113 return (real_t)(d_uns64)value; | |
1114 else | |
1115 return (real_t)(d_int64)value; | |
1116 } | |
1117 | |
1118 real_t IntegerExp::toImaginary() | |
1119 { | |
1120 return (real_t) 0; | |
1121 } | |
1122 | |
1123 complex_t IntegerExp::toComplex() | |
1124 { | |
1125 return toReal(); | |
1126 } | |
1127 | |
1128 int IntegerExp::isBool(int result) | |
1129 { | |
1130 return result ? value != 0 : value == 0; | |
1131 } | |
1132 | |
1133 Expression *IntegerExp::semantic(Scope *sc) | |
1134 { | |
1135 if (!type) | |
1136 { | |
1137 // Determine what the type of this number is | |
1138 integer_t number = value; | |
1139 | |
1140 if (number & 0x8000000000000000LL) | |
1141 type = Type::tuns64; | |
1142 else if (number & 0xFFFFFFFF80000000LL) | |
1143 type = Type::tint64; | |
1144 else | |
1145 type = Type::tint32; | |
1146 } | |
1147 else | |
1148 { type = type->semantic(loc, sc); | |
1149 } | |
1150 return this; | |
1151 } | |
1152 | |
1153 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e) | |
1154 { | |
1155 if (!e) | |
1156 e = this; | |
1157 else if (!loc.filename) | |
1158 loc = e->loc; | |
1159 e->error("constant %s is not an lvalue", e->toChars()); | |
1160 return this; | |
1161 } | |
1162 | |
1163 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1164 { | |
1165 integer_t v = toInteger(); | |
1166 | |
1167 if (type) | |
1168 { Type *t = type; | |
1169 | |
1170 L1: | |
1171 switch (t->ty) | |
1172 { | |
1173 case Tenum: | |
1174 { TypeEnum *te = (TypeEnum *)t; | |
1175 buf->printf("cast(%s)", te->sym->toChars()); | |
1176 t = te->sym->memtype; | |
1177 goto L1; | |
1178 } | |
1179 | |
1180 case Ttypedef: | |
1181 { TypeTypedef *tt = (TypeTypedef *)t; | |
1182 buf->printf("cast(%s)", tt->sym->toChars()); | |
1183 t = tt->sym->basetype; | |
1184 goto L1; | |
1185 } | |
1186 | |
1187 case Twchar: // BUG: need to cast(wchar) | |
1188 case Tdchar: // BUG: need to cast(dchar) | |
1189 if ((uinteger_t)v > 0xFF) | |
1190 { | |
1191 buf->printf("'\\U%08x'", v); | |
1192 break; | |
1193 } | |
1194 case Tchar: | |
1195 if (v == '\'') | |
1196 buf->writestring("'\\''"); | |
1197 else if (isprint(v) && v != '\\') | |
1198 buf->printf("'%c'", (int)v); | |
1199 else | |
1200 buf->printf("'\\x%02x'", (int)v); | |
1201 break; | |
1202 | |
1203 case Tint8: | |
1204 buf->writestring("cast(byte)"); | |
1205 goto L2; | |
1206 | |
1207 case Tint16: | |
1208 buf->writestring("cast(short)"); | |
1209 goto L2; | |
1210 | |
1211 case Tint32: | |
1212 L2: | |
1213 buf->printf("%d", (int)v); | |
1214 break; | |
1215 | |
1216 case Tuns8: | |
1217 buf->writestring("cast(ubyte)"); | |
1218 goto L3; | |
1219 | |
1220 case Tuns16: | |
1221 buf->writestring("cast(ushort)"); | |
1222 goto L3; | |
1223 | |
1224 case Tuns32: | |
1225 L3: | |
1226 buf->printf("%du", (unsigned)v); | |
1227 break; | |
1228 | |
1229 case Tint64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1230 buf->printf("%lldL", v); |
159 | 1231 break; |
1232 | |
1233 case Tuns64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1234 buf->printf("%lluLU", v); |
159 | 1235 break; |
1236 | |
1237 case Tbit: | |
1238 case Tbool: | |
1239 buf->writestring((char *)(v ? "true" : "false")); | |
1240 break; | |
1241 | |
1242 case Tpointer: | |
1243 buf->writestring("cast("); | |
1244 buf->writestring(t->toChars()); | |
1245 buf->writeByte(')'); | |
1246 goto L3; | |
1247 | |
1248 default: | |
1249 #ifdef DEBUG | |
1250 t->print(); | |
1251 #endif | |
1252 assert(0); | |
1253 } | |
1254 } | |
1255 else if (v & 0x8000000000000000LL) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1256 buf->printf("0x%llx", v); |
159 | 1257 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1258 buf->printf("%lld", v); |
159 | 1259 } |
1260 | |
1261 void IntegerExp::toMangleBuffer(OutBuffer *buf) | |
1262 { | |
1263 if ((sinteger_t)value < 0) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1264 buf->printf("N%lld", -value); |
159 | 1265 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1266 buf->printf("%lld", value); |
159 | 1267 } |
1268 | |
1269 /******************************** RealExp **************************/ | |
1270 | |
1271 RealExp::RealExp(Loc loc, real_t value, Type *type) | |
1272 : Expression(loc, TOKfloat64, sizeof(RealExp)) | |
1273 { | |
1274 //printf("RealExp::RealExp(%Lg)\n", value); | |
1275 this->value = value; | |
1276 this->type = type; | |
1277 } | |
1278 | |
1279 char *RealExp::toChars() | |
1280 { | |
1281 char buffer[sizeof(value) * 3 + 8 + 1 + 1]; | |
1282 | |
1283 #ifdef IN_GCC | |
1284 value.format(buffer, sizeof(buffer)); | |
1285 if (type->isimaginary()) | |
1286 strcat(buffer, "i"); | |
1287 #else | |
1288 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value); | |
1289 #endif | |
1290 assert(strlen(buffer) < sizeof(buffer)); | |
1291 return mem.strdup(buffer); | |
1292 } | |
1293 | |
1294 integer_t RealExp::toInteger() | |
1295 { | |
1296 #ifdef IN_GCC | |
1297 return toReal().toInt(); | |
1298 #else | |
1299 return (sinteger_t) toReal(); | |
1300 #endif | |
1301 } | |
1302 | |
1303 uinteger_t RealExp::toUInteger() | |
1304 { | |
1305 #ifdef IN_GCC | |
1306 return (uinteger_t) toReal().toInt(); | |
1307 #else | |
1308 return (uinteger_t) toReal(); | |
1309 #endif | |
1310 } | |
1311 | |
1312 real_t RealExp::toReal() | |
1313 { | |
1314 return type->isreal() ? value : 0; | |
1315 } | |
1316 | |
1317 real_t RealExp::toImaginary() | |
1318 { | |
1319 return type->isreal() ? 0 : value; | |
1320 } | |
1321 | |
1322 complex_t RealExp::toComplex() | |
1323 { | |
1324 #ifdef __DMC__ | |
1325 return toReal() + toImaginary() * I; | |
1326 #else | |
1327 return complex_t(toReal(), toImaginary()); | |
1328 #endif | |
1329 } | |
1330 | |
1331 /******************************** | |
1332 * Test to see if two reals are the same. | |
1333 * Regard NaN's as equivalent. | |
1334 * Regard +0 and -0 as different. | |
1335 */ | |
1336 | |
1337 int RealEquals(real_t x1, real_t x2) | |
1338 { | |
1339 return (isnan(x1) && isnan(x2)) || | |
1340 /* In some cases, the REALPAD bytes get garbage in them, | |
1341 * so be sure and ignore them. | |
1342 */ | |
1343 memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; | |
1344 } | |
1345 | |
1346 int RealExp::equals(Object *o) | |
1347 { RealExp *ne; | |
1348 | |
1349 if (this == o || | |
1350 (((Expression *)o)->op == TOKfloat64 && | |
1351 ((ne = (RealExp *)o), type->equals(ne->type)) && | |
1352 RealEquals(value, ne->value) | |
1353 ) | |
1354 ) | |
1355 return 1; | |
1356 return 0; | |
1357 } | |
1358 | |
1359 Expression *RealExp::semantic(Scope *sc) | |
1360 { | |
1361 if (!type) | |
1362 type = Type::tfloat64; | |
1363 else | |
1364 type = type->semantic(loc, sc); | |
1365 return this; | |
1366 } | |
1367 | |
1368 int RealExp::isBool(int result) | |
1369 { | |
1370 #ifdef IN_GCC | |
1371 return result ? (! value.isZero()) : (value.isZero()); | |
1372 #else | |
1373 return result ? (value != 0) | |
1374 : (value == 0); | |
1375 #endif | |
1376 } | |
1377 | |
1378 void floatToBuffer(OutBuffer *buf, Type *type, real_t value) | |
1379 { | |
1380 /* In order to get an exact representation, try converting it | |
1381 * to decimal then back again. If it matches, use it. | |
1382 * If it doesn't, fall back to hex, which is | |
1383 * always exact. | |
1384 */ | |
1385 char buffer[25]; | |
1386 sprintf(buffer, "%Lg", value); | |
1387 assert(strlen(buffer) < sizeof(buffer)); | |
1388 #if _WIN32 && __DMC__ | |
1389 char *save = __locale_decpoint; | |
1390 __locale_decpoint = "."; | |
1391 real_t r = strtold(buffer, NULL); | |
1392 __locale_decpoint = save; | |
1393 #else | |
1394 real_t r = strtold(buffer, NULL); | |
1395 #endif | |
1396 if (r == value) // if exact duplication | |
1397 buf->writestring(buffer); | |
1398 else | |
1399 buf->printf("%La", value); // ensure exact duplication | |
1400 | |
1401 if (type) | |
1402 { | |
1403 Type *t = type->toBasetype(); | |
1404 switch (t->ty) | |
1405 { | |
1406 case Tfloat32: | |
1407 case Timaginary32: | |
1408 case Tcomplex32: | |
1409 buf->writeByte('F'); | |
1410 break; | |
1411 | |
1412 case Tfloat80: | |
1413 case Timaginary80: | |
1414 case Tcomplex80: | |
1415 buf->writeByte('L'); | |
1416 break; | |
1417 | |
1418 default: | |
1419 break; | |
1420 } | |
1421 if (t->isimaginary()) | |
1422 buf->writeByte('i'); | |
1423 } | |
1424 } | |
1425 | |
1426 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1427 { | |
1428 floatToBuffer(buf, type, value); | |
1429 } | |
1430 | |
1431 void realToMangleBuffer(OutBuffer *buf, real_t value) | |
1432 { | |
1433 /* Rely on %A to get portable mangling. | |
1434 * Must munge result to get only identifier characters. | |
1435 * | |
1436 * Possible values from %A => mangled result | |
1437 * NAN => NAN | |
1438 * -INF => NINF | |
1439 * INF => INF | |
1440 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 | |
1441 * 0X1.9P+2 => 19P2 | |
1442 */ | |
1443 | |
1444 if (isnan(value)) | |
1445 buf->writestring("NAN"); // no -NAN bugs | |
1446 else | |
1447 { | |
1448 char buffer[32]; | |
1449 int n = sprintf(buffer, "%LA", value); | |
1450 assert(n > 0 && n < sizeof(buffer)); | |
1451 for (int i = 0; i < n; i++) | |
1452 { char c = buffer[i]; | |
1453 | |
1454 switch (c) | |
1455 { | |
1456 case '-': | |
1457 buf->writeByte('N'); | |
1458 break; | |
1459 | |
1460 case '+': | |
1461 case 'X': | |
1462 case '.': | |
1463 break; | |
1464 | |
1465 case '0': | |
1466 if (i < 2) | |
1467 break; // skip leading 0X | |
1468 default: | |
1469 buf->writeByte(c); | |
1470 break; | |
1471 } | |
1472 } | |
1473 } | |
1474 } | |
1475 | |
1476 void RealExp::toMangleBuffer(OutBuffer *buf) | |
1477 { | |
1478 buf->writeByte('e'); | |
1479 realToMangleBuffer(buf, value); | |
1480 } | |
1481 | |
1482 | |
1483 /******************************** ComplexExp **************************/ | |
1484 | |
1485 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type) | |
1486 : Expression(loc, TOKcomplex80, sizeof(ComplexExp)) | |
1487 { | |
1488 this->value = value; | |
1489 this->type = type; | |
1490 //printf("ComplexExp::ComplexExp(%s)\n", toChars()); | |
1491 } | |
1492 | |
1493 char *ComplexExp::toChars() | |
1494 { | |
1495 char buffer[sizeof(value) * 3 + 8 + 1]; | |
1496 | |
1497 #ifdef IN_GCC | |
1498 char buf1[sizeof(value) * 3 + 8 + 1]; | |
1499 char buf2[sizeof(value) * 3 + 8 + 1]; | |
1500 creall(value).format(buf1, sizeof(buf1)); | |
1501 cimagl(value).format(buf2, sizeof(buf2)); | |
1502 sprintf(buffer, "(%s+%si)", buf1, buf2); | |
1503 #else | |
1504 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value)); | |
1505 assert(strlen(buffer) < sizeof(buffer)); | |
1506 #endif | |
1507 return mem.strdup(buffer); | |
1508 } | |
1509 | |
1510 integer_t ComplexExp::toInteger() | |
1511 { | |
1512 #ifdef IN_GCC | |
1513 return (sinteger_t) toReal().toInt(); | |
1514 #else | |
1515 return (sinteger_t) toReal(); | |
1516 #endif | |
1517 } | |
1518 | |
1519 uinteger_t ComplexExp::toUInteger() | |
1520 { | |
1521 #ifdef IN_GCC | |
1522 return (uinteger_t) toReal().toInt(); | |
1523 #else | |
1524 return (uinteger_t) toReal(); | |
1525 #endif | |
1526 } | |
1527 | |
1528 real_t ComplexExp::toReal() | |
1529 { | |
1530 return creall(value); | |
1531 } | |
1532 | |
1533 real_t ComplexExp::toImaginary() | |
1534 { | |
1535 return cimagl(value); | |
1536 } | |
1537 | |
1538 complex_t ComplexExp::toComplex() | |
1539 { | |
1540 return value; | |
1541 } | |
1542 | |
1543 int ComplexExp::equals(Object *o) | |
1544 { ComplexExp *ne; | |
1545 | |
1546 if (this == o || | |
1547 (((Expression *)o)->op == TOKcomplex80 && | |
1548 ((ne = (ComplexExp *)o), type->equals(ne->type)) && | |
1549 RealEquals(creall(value), creall(ne->value)) && | |
1550 RealEquals(cimagl(value), cimagl(ne->value)) | |
1551 ) | |
1552 ) | |
1553 return 1; | |
1554 return 0; | |
1555 } | |
1556 | |
1557 Expression *ComplexExp::semantic(Scope *sc) | |
1558 { | |
1559 if (!type) | |
1560 type = Type::tcomplex80; | |
1561 else | |
1562 type = type->semantic(loc, sc); | |
1563 return this; | |
1564 } | |
1565 | |
1566 int ComplexExp::isBool(int result) | |
1567 { | |
1568 if (result) | |
1569 return (bool)(value); | |
1570 else | |
1571 return !value; | |
1572 } | |
1573 | |
1574 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1575 { | |
1576 /* Print as: | |
1577 * (re+imi) | |
1578 */ | |
1579 #ifdef IN_GCC | |
1580 char buf1[sizeof(value) * 3 + 8 + 1]; | |
1581 char buf2[sizeof(value) * 3 + 8 + 1]; | |
1582 creall(value).format(buf1, sizeof(buf1)); | |
1583 cimagl(value).format(buf2, sizeof(buf2)); | |
1584 buf->printf("(%s+%si)", buf1, buf2); | |
1585 #else | |
1586 buf->writeByte('('); | |
1587 floatToBuffer(buf, type, creall(value)); | |
1588 buf->writeByte('+'); | |
1589 floatToBuffer(buf, type, cimagl(value)); | |
1590 buf->writestring("i)"); | |
1591 #endif | |
1592 } | |
1593 | |
1594 void ComplexExp::toMangleBuffer(OutBuffer *buf) | |
1595 { | |
1596 buf->writeByte('c'); | |
1597 real_t r = toReal(); | |
1598 realToMangleBuffer(buf, r); | |
1599 buf->writeByte('c'); // separate the two | |
1600 r = toImaginary(); | |
1601 realToMangleBuffer(buf, r); | |
1602 } | |
1603 | |
1604 /******************************** IdentifierExp **************************/ | |
1605 | |
1606 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident) | |
1607 : Expression(loc, TOKidentifier, sizeof(IdentifierExp)) | |
1608 { | |
1609 this->ident = ident; | |
1610 } | |
1611 | |
1612 Expression *IdentifierExp::semantic(Scope *sc) | |
1613 { | |
1614 Dsymbol *s; | |
1615 Dsymbol *scopesym; | |
1616 | |
1617 #if LOGSEMANTIC | |
1618 printf("IdentifierExp::semantic('%s')\n", ident->toChars()); | |
1619 #endif | |
1620 s = sc->search(loc, ident, &scopesym); | |
1621 if (s) | |
1622 { Expression *e; | |
1623 WithScopeSymbol *withsym; | |
1624 | |
1625 // See if it was a with class | |
1626 withsym = scopesym->isWithScopeSymbol(); | |
1627 if (withsym) | |
1628 { | |
1629 s = s->toAlias(); | |
1630 | |
1631 // Same as wthis.ident | |
1632 if (s->needThis() || s->isTemplateDeclaration()) | |
1633 { | |
1634 e = new VarExp(loc, withsym->withstate->wthis); | |
1635 e = new DotIdExp(loc, e, ident); | |
1636 } | |
1637 else | |
1638 { Type *t = withsym->withstate->wthis->type; | |
1639 if (t->ty == Tpointer) | |
1640 t = t->next; | |
1641 e = new TypeDotIdExp(loc, t, ident); | |
1642 } | |
1643 } | |
1644 else | |
1645 { | |
1646 if (!s->parent && scopesym->isArrayScopeSymbol()) | |
1647 { // Kludge to run semantic() here because | |
1648 // ArrayScopeSymbol::search() doesn't have access to sc. | |
1649 s->semantic(sc); | |
1650 } | |
1651 // Look to see if f is really a function template | |
1652 FuncDeclaration *f = s->isFuncDeclaration(); | |
1653 if (f && f->parent) | |
1654 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
1655 | |
1656 if (ti && | |
1657 !ti->isTemplateMixin() && | |
1658 (ti->name == f->ident || | |
1659 ti->toAlias()->ident == f->ident) | |
1660 && | |
1661 ti->tempdecl && ti->tempdecl->onemember) | |
1662 { | |
1663 TemplateDeclaration *tempdecl = ti->tempdecl; | |
1664 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
1665 tempdecl = tempdecl->overroot; // then get the start | |
1666 e = new TemplateExp(loc, tempdecl); | |
1667 e = e->semantic(sc); | |
1668 return e; | |
1669 } | |
1670 } | |
1671 e = new DsymbolExp(loc, s); | |
1672 } | |
1673 return e->semantic(sc); | |
1674 } | |
1675 error("undefined identifier %s", ident->toChars()); | |
1676 type = Type::terror; | |
1677 return this; | |
1678 } | |
1679 | |
1680 char *IdentifierExp::toChars() | |
1681 { | |
1682 return ident->toChars(); | |
1683 } | |
1684 | |
1685 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1686 { | |
1687 if (hgs->hdrgen) | |
1688 buf->writestring(ident->toHChars2()); | |
1689 else | |
1690 buf->writestring(ident->toChars()); | |
1691 } | |
1692 | |
1693 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e) | |
1694 { | |
1695 #if 0 | |
1696 tym = tybasic(e1->ET->Tty); | |
1697 if (!(tyscalar(tym) || | |
1698 tym == TYstruct || | |
1699 tym == TYarray && e->Eoper == TOKaddr)) | |
1700 synerr(EM_lvalue); // lvalue expected | |
1701 #endif | |
1702 return this; | |
1703 } | |
1704 | |
1705 /******************************** DollarExp **************************/ | |
1706 | |
1707 DollarExp::DollarExp(Loc loc) | |
1708 : IdentifierExp(loc, Id::dollar) | |
1709 { | |
1710 } | |
1711 | |
1712 /******************************** DsymbolExp **************************/ | |
1713 | |
1714 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s) | |
1715 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp)) | |
1716 { | |
1717 this->s = s; | |
1718 } | |
1719 | |
1720 Expression *DsymbolExp::semantic(Scope *sc) | |
1721 { | |
1722 #if LOGSEMANTIC | |
1723 printf("DsymbolExp::semantic('%s')\n", s->toChars()); | |
1724 #endif | |
1725 | |
1726 Lagain: | |
1727 EnumMember *em; | |
1728 Expression *e; | |
1729 VarDeclaration *v; | |
1730 FuncDeclaration *f; | |
1731 FuncLiteralDeclaration *fld; | |
1732 Declaration *d; | |
1733 ClassDeclaration *cd; | |
1734 ClassDeclaration *thiscd = NULL; | |
1735 Import *imp; | |
1736 Package *pkg; | |
1737 Type *t; | |
1738 | |
1739 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); | |
1740 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); | |
1741 if (type) | |
1742 return this; | |
1743 if (!s->isFuncDeclaration()) // functions are checked after overloading | |
1744 checkDeprecated(sc, s); | |
1745 s = s->toAlias(); | |
1746 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis()); | |
1747 if (!s->isFuncDeclaration()) | |
1748 checkDeprecated(sc, s); | |
1749 | |
1750 if (sc->func) | |
1751 thiscd = sc->func->parent->isClassDeclaration(); | |
1752 | |
1753 // BUG: This should happen after overload resolution for functions, not before | |
1754 if (s->needThis()) | |
1755 { | |
1756 if (hasThis(sc) /*&& !s->isFuncDeclaration()*/) | |
1757 { | |
1758 // Supply an implicit 'this', as in | |
1759 // this.ident | |
1760 | |
1761 DotVarExp *de; | |
1762 | |
1763 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration()); | |
1764 return de->semantic(sc); | |
1765 } | |
1766 } | |
1767 | |
1768 em = s->isEnumMember(); | |
1769 if (em) | |
1770 { | |
1771 e = em->value->copy(); | |
1772 e = e->semantic(sc); | |
1773 return e; | |
1774 } | |
1775 v = s->isVarDeclaration(); | |
1776 if (v) | |
1777 { | |
1778 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
1779 if (!type) | |
1780 { type = v->type; | |
1781 if (!v->type) | |
1782 { error("forward reference of %s", v->toChars()); | |
1783 type = Type::terror; | |
1784 } | |
1785 } | |
1786 if (v->isConst() && type->toBasetype()->ty != Tsarray) | |
1787 { | |
1788 if (v->init) | |
1789 { | |
1790 if (v->inuse) | |
1791 { | |
1792 error("circular reference to '%s'", v->toChars()); | |
1793 type = Type::tint32; | |
1794 return this; | |
1795 } | |
1796 ExpInitializer *ei = v->init->isExpInitializer(); | |
1797 if (ei) | |
1798 { | |
1799 e = ei->exp->copy(); // make copy so we can change loc | |
1800 if (e->op == TOKstring || !e->type) | |
1801 e = e->semantic(sc); | |
1802 e = e->implicitCastTo(sc, type); | |
1803 e->loc = loc; | |
1804 return e; | |
1805 } | |
1806 } | |
1807 else | |
1808 { | |
1809 e = type->defaultInit(); | |
1810 e->loc = loc; | |
1811 return e; | |
1812 } | |
1813 } | |
1814 e = new VarExp(loc, v); | |
1815 e->type = type; | |
1816 e = e->semantic(sc); | |
1817 return e->deref(); | |
1818 } | |
1819 fld = s->isFuncLiteralDeclaration(); | |
1820 if (fld) | |
1821 { //printf("'%s' is a function literal\n", fld->toChars()); | |
1822 e = new FuncExp(loc, fld); | |
1823 return e->semantic(sc); | |
1824 } | |
1825 f = s->isFuncDeclaration(); | |
1826 if (f) | |
1827 { //printf("'%s' is a function\n", f->toChars()); | |
1828 return new VarExp(loc, f); | |
1829 } | |
1830 cd = s->isClassDeclaration(); | |
1831 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis()) | |
1832 { | |
1833 // We need to add an implicit 'this' if cd is this class or a base class. | |
1834 DotTypeExp *dte; | |
1835 | |
1836 dte = new DotTypeExp(loc, new ThisExp(loc), s); | |
1837 return dte->semantic(sc); | |
1838 } | |
1839 imp = s->isImport(); | |
1840 if (imp) | |
1841 { | |
1842 ScopeExp *ie; | |
1843 | |
1844 ie = new ScopeExp(loc, imp->pkg); | |
1845 return ie->semantic(sc); | |
1846 } | |
1847 pkg = s->isPackage(); | |
1848 if (pkg) | |
1849 { | |
1850 ScopeExp *ie; | |
1851 | |
1852 ie = new ScopeExp(loc, pkg); | |
1853 return ie->semantic(sc); | |
1854 } | |
1855 Module *mod = s->isModule(); | |
1856 if (mod) | |
1857 { | |
1858 ScopeExp *ie; | |
1859 | |
1860 ie = new ScopeExp(loc, mod); | |
1861 return ie->semantic(sc); | |
1862 } | |
1863 | |
1864 t = s->getType(); | |
1865 if (t) | |
1866 { | |
1867 return new TypeExp(loc, t); | |
1868 } | |
1869 | |
1870 TupleDeclaration *tup = s->isTupleDeclaration(); | |
1871 if (tup) | |
1872 { | |
1873 e = new TupleExp(loc, tup); | |
1874 e = e->semantic(sc); | |
1875 return e; | |
1876 } | |
1877 | |
1878 TemplateInstance *ti = s->isTemplateInstance(); | |
1879 if (ti && !global.errors) | |
1880 { if (!ti->semanticdone) | |
1881 ti->semantic(sc); | |
1882 s = ti->inst->toAlias(); | |
1883 if (!s->isTemplateInstance()) | |
1884 goto Lagain; | |
1885 e = new ScopeExp(loc, ti); | |
1886 e = e->semantic(sc); | |
1887 return e; | |
1888 } | |
1889 | |
1890 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
1891 if (td) | |
1892 { | |
1893 e = new TemplateExp(loc, td); | |
1894 e = e->semantic(sc); | |
1895 return e; | |
1896 } | |
1897 | |
1898 Lerr: | |
1899 error("%s '%s' is not a variable", s->kind(), s->toChars()); | |
1900 type = Type::terror; | |
1901 return this; | |
1902 } | |
1903 | |
1904 char *DsymbolExp::toChars() | |
1905 { | |
1906 return s->toChars(); | |
1907 } | |
1908 | |
1909 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1910 { | |
1911 buf->writestring(s->toChars()); | |
1912 } | |
1913 | |
1914 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e) | |
1915 { | |
1916 #if 0 | |
1917 tym = tybasic(e1->ET->Tty); | |
1918 if (!(tyscalar(tym) || | |
1919 tym == TYstruct || | |
1920 tym == TYarray && e->Eoper == TOKaddr)) | |
1921 synerr(EM_lvalue); // lvalue expected | |
1922 #endif | |
1923 return this; | |
1924 } | |
1925 | |
1926 /******************************** ThisExp **************************/ | |
1927 | |
1928 ThisExp::ThisExp(Loc loc) | |
1929 : Expression(loc, TOKthis, sizeof(ThisExp)) | |
1930 { | |
1931 var = NULL; | |
1932 } | |
1933 | |
1934 Expression *ThisExp::semantic(Scope *sc) | |
1935 { FuncDeclaration *fd; | |
1936 FuncDeclaration *fdthis; | |
1937 int nested = 0; | |
1938 | |
1939 #if LOGSEMANTIC | |
1940 printf("ThisExp::semantic()\n"); | |
1941 #endif | |
1942 if (type) | |
1943 { //assert(global.errors || var); | |
1944 return this; | |
1945 } | |
1946 | |
1947 /* Special case for typeof(this) and typeof(super) since both | |
1948 * should work even if they are not inside a non-static member function | |
1949 */ | |
1950 if (sc->intypeof) | |
1951 { | |
1952 // Find enclosing struct or class | |
1953 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
1954 { | |
1955 ClassDeclaration *cd; | |
1956 StructDeclaration *sd; | |
1957 | |
1958 if (!s) | |
1959 { | |
1960 error("%s is not in a struct or class scope", toChars()); | |
1961 goto Lerr; | |
1962 } | |
1963 cd = s->isClassDeclaration(); | |
1964 if (cd) | |
1965 { | |
1966 type = cd->type; | |
1967 return this; | |
1968 } | |
1969 sd = s->isStructDeclaration(); | |
1970 if (sd) | |
1971 { | |
1972 type = sd->type->pointerTo(); | |
1973 return this; | |
1974 } | |
1975 } | |
1976 } | |
1977 | |
1978 fdthis = sc->parent->isFuncDeclaration(); | |
1979 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable | |
1980 if (!fd) | |
1981 goto Lerr; | |
1982 | |
1983 assert(fd->vthis); | |
1984 var = fd->vthis; | |
1985 assert(var->parent); | |
1986 type = var->type; | |
1987 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
1988 #if 0 | |
1989 if (fd != fdthis) // if nested | |
1990 { | |
1991 fdthis->getLevel(loc, fd); | |
1992 fd->vthis->nestedref = 1; | |
1993 fd->nestedFrameRef = 1; | |
1994 } | |
1995 #endif | |
1996 sc->callSuper |= CSXthis; | |
1997 return this; | |
1998 | |
1999 Lerr: | |
2000 error("'this' is only allowed in non-static member functions, not %s", sc->parent->toChars()); | |
2001 type = Type::tint32; | |
2002 return this; | |
2003 } | |
2004 | |
2005 int ThisExp::isBool(int result) | |
2006 { | |
2007 return result ? TRUE : FALSE; | |
2008 } | |
2009 | |
2010 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2011 { | |
2012 buf->writestring("this"); | |
2013 } | |
2014 | |
2015 Expression *ThisExp::toLvalue(Scope *sc, Expression *e) | |
2016 { | |
2017 return this; | |
2018 } | |
2019 | |
2020 /******************************** SuperExp **************************/ | |
2021 | |
2022 SuperExp::SuperExp(Loc loc) | |
2023 : ThisExp(loc) | |
2024 { | |
2025 op = TOKsuper; | |
2026 } | |
2027 | |
2028 Expression *SuperExp::semantic(Scope *sc) | |
2029 { FuncDeclaration *fd; | |
2030 FuncDeclaration *fdthis; | |
2031 ClassDeclaration *cd; | |
2032 Dsymbol *s; | |
2033 | |
2034 #if LOGSEMANTIC | |
2035 printf("SuperExp::semantic('%s')\n", toChars()); | |
2036 #endif | |
2037 if (type) | |
2038 return this; | |
2039 | |
2040 /* Special case for typeof(this) and typeof(super) since both | |
2041 * should work even if they are not inside a non-static member function | |
2042 */ | |
2043 if (sc->intypeof) | |
2044 { | |
2045 // Find enclosing class | |
2046 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
2047 { | |
2048 ClassDeclaration *cd; | |
2049 | |
2050 if (!s) | |
2051 { | |
2052 error("%s is not in a class scope", toChars()); | |
2053 goto Lerr; | |
2054 } | |
2055 cd = s->isClassDeclaration(); | |
2056 if (cd) | |
2057 { | |
2058 cd = cd->baseClass; | |
2059 if (!cd) | |
2060 { error("class %s has no 'super'", s->toChars()); | |
2061 goto Lerr; | |
2062 } | |
2063 type = cd->type; | |
2064 return this; | |
2065 } | |
2066 } | |
2067 } | |
2068 | |
2069 fdthis = sc->parent->isFuncDeclaration(); | |
2070 fd = hasThis(sc); | |
2071 if (!fd) | |
2072 goto Lerr; | |
2073 assert(fd->vthis); | |
2074 var = fd->vthis; | |
2075 assert(var->parent); | |
2076 | |
2077 s = fd->toParent(); | |
2078 while (s && s->isTemplateInstance()) | |
2079 s = s->toParent(); | |
2080 assert(s); | |
2081 cd = s->isClassDeclaration(); | |
2082 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars()); | |
2083 if (!cd) | |
2084 goto Lerr; | |
2085 if (!cd->baseClass) | |
2086 { | |
2087 error("no base class for %s", cd->toChars()); | |
2088 type = fd->vthis->type; | |
2089 } | |
2090 else | |
2091 { | |
2092 type = cd->baseClass->type; | |
2093 } | |
2094 | |
2095 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
2096 #if 0 | |
2097 if (fd != fdthis) | |
2098 { | |
2099 fdthis->getLevel(loc, fd); | |
2100 fd->vthis->nestedref = 1; | |
2101 fd->nestedFrameRef = 1; | |
2102 } | |
2103 #endif | |
2104 | |
2105 sc->callSuper |= CSXsuper; | |
2106 return this; | |
2107 | |
2108 | |
2109 Lerr: | |
2110 error("'super' is only allowed in non-static class member functions"); | |
2111 type = Type::tint32; | |
2112 return this; | |
2113 } | |
2114 | |
2115 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2116 { | |
2117 buf->writestring("super"); | |
2118 } | |
2119 | |
2120 | |
2121 /******************************** NullExp **************************/ | |
2122 | |
2123 NullExp::NullExp(Loc loc) | |
2124 : Expression(loc, TOKnull, sizeof(NullExp)) | |
2125 { | |
2126 committed = 0; | |
2127 } | |
2128 | |
2129 Expression *NullExp::semantic(Scope *sc) | |
2130 { | |
2131 #if LOGSEMANTIC | |
2132 printf("NullExp::semantic('%s')\n", toChars()); | |
2133 #endif | |
2134 // NULL is the same as (void *)0 | |
2135 if (!type) | |
2136 type = Type::tvoid->pointerTo(); | |
2137 return this; | |
2138 } | |
2139 | |
2140 int NullExp::isBool(int result) | |
2141 { | |
2142 return result ? FALSE : TRUE; | |
2143 } | |
2144 | |
2145 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2146 { | |
2147 buf->writestring("null"); | |
2148 } | |
2149 | |
2150 void NullExp::toMangleBuffer(OutBuffer *buf) | |
2151 { | |
2152 buf->writeByte('n'); | |
2153 } | |
2154 | |
2155 /******************************** StringExp **************************/ | |
2156 | |
2157 StringExp::StringExp(Loc loc, char *string) | |
2158 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2159 { | |
2160 this->string = string; | |
2161 this->len = strlen(string); | |
2162 this->sz = 1; | |
2163 this->committed = 0; | |
2164 this->postfix = 0; | |
2165 } | |
2166 | |
2167 StringExp::StringExp(Loc loc, void *string, size_t len) | |
2168 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2169 { | |
2170 this->string = string; | |
2171 this->len = len; | |
2172 this->sz = 1; | |
2173 this->committed = 0; | |
2174 this->postfix = 0; | |
2175 } | |
2176 | |
2177 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix) | |
2178 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2179 { | |
2180 this->string = string; | |
2181 this->len = len; | |
2182 this->sz = 1; | |
2183 this->committed = 0; | |
2184 this->postfix = postfix; | |
2185 } | |
2186 | |
2187 #if 0 | |
2188 Expression *StringExp::syntaxCopy() | |
2189 { | |
2190 printf("StringExp::syntaxCopy() %s\n", toChars()); | |
2191 return copy(); | |
2192 } | |
2193 #endif | |
2194 | |
2195 int StringExp::equals(Object *o) | |
2196 { | |
2197 //printf("StringExp::equals('%s')\n", o->toChars()); | |
2198 if (o && o->dyncast() == DYNCAST_EXPRESSION) | |
2199 { Expression *e = (Expression *)o; | |
2200 | |
2201 if (e->op == TOKstring) | |
2202 { | |
2203 return compare(o) == 0; | |
2204 } | |
2205 } | |
2206 return FALSE; | |
2207 } | |
2208 | |
2209 char *StringExp::toChars() | |
2210 { | |
2211 OutBuffer buf; | |
2212 HdrGenState hgs; | |
2213 char *p; | |
2214 | |
2215 memset(&hgs, 0, sizeof(hgs)); | |
2216 toCBuffer(&buf, &hgs); | |
2217 buf.writeByte(0); | |
2218 p = (char *)buf.data; | |
2219 buf.data = NULL; | |
2220 return p; | |
2221 } | |
2222 | |
2223 Expression *StringExp::semantic(Scope *sc) | |
2224 { | |
2225 #if LOGSEMANTIC | |
2226 printf("StringExp::semantic() %s\n", toChars()); | |
2227 #endif | |
2228 if (!type) | |
2229 { OutBuffer buffer; | |
2230 size_t newlen = 0; | |
2231 char *p; | |
2232 size_t u; | |
2233 unsigned c; | |
2234 | |
2235 switch (postfix) | |
2236 { | |
2237 case 'd': | |
2238 for (u = 0; u < len;) | |
2239 { | |
2240 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2241 if (p) | |
2242 { error("%s", p); | |
2243 break; | |
2244 } | |
2245 else | |
2246 { buffer.write4(c); | |
2247 newlen++; | |
2248 } | |
2249 } | |
2250 buffer.write4(0); | |
2251 string = buffer.extractData(); | |
2252 len = newlen; | |
2253 sz = 4; | |
2254 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex)); | |
2255 committed = 1; | |
2256 break; | |
2257 | |
2258 case 'w': | |
2259 for (u = 0; u < len;) | |
2260 { | |
2261 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2262 if (p) | |
2263 { error("%s", p); | |
2264 break; | |
2265 } | |
2266 else | |
2267 { buffer.writeUTF16(c); | |
2268 newlen++; | |
2269 if (c >= 0x10000) | |
2270 newlen++; | |
2271 } | |
2272 } | |
2273 buffer.writeUTF16(0); | |
2274 string = buffer.extractData(); | |
2275 len = newlen; | |
2276 sz = 2; | |
2277 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex)); | |
2278 committed = 1; | |
2279 break; | |
2280 | |
2281 case 'c': | |
2282 committed = 1; | |
2283 default: | |
2284 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); | |
2285 break; | |
2286 } | |
2287 type = type->semantic(loc, sc); | |
2288 } | |
2289 return this; | |
2290 } | |
2291 | |
2292 /**************************************** | |
2293 * Convert string to char[]. | |
2294 */ | |
2295 | |
2296 StringExp *StringExp::toUTF8(Scope *sc) | |
2297 { | |
2298 if (sz != 1) | |
2299 { // Convert to UTF-8 string | |
2300 committed = 0; | |
2301 Expression *e = castTo(sc, Type::tchar->arrayOf()); | |
2302 e = e->optimize(WANTvalue); | |
2303 assert(e->op == TOKstring); | |
2304 StringExp *se = (StringExp *)e; | |
2305 assert(se->sz == 1); | |
2306 return se; | |
2307 } | |
2308 return this; | |
2309 } | |
2310 | |
2311 int StringExp::compare(Object *obj) | |
2312 { | |
2313 // Used to sort case statement expressions so we can do an efficient lookup | |
2314 StringExp *se2 = (StringExp *)(obj); | |
2315 | |
2316 // This is a kludge so isExpression() in template.c will return 5 | |
2317 // for StringExp's. | |
2318 if (!se2) | |
2319 return 5; | |
2320 | |
2321 assert(se2->op == TOKstring); | |
2322 | |
2323 int len1 = len; | |
2324 int len2 = se2->len; | |
2325 | |
2326 if (len1 == len2) | |
2327 { | |
2328 switch (sz) | |
2329 { | |
2330 case 1: | |
2331 return strcmp((char *)string, (char *)se2->string); | |
2332 | |
2333 case 2: | |
2334 { unsigned u; | |
2335 d_wchar *s1 = (d_wchar *)string; | |
2336 d_wchar *s2 = (d_wchar *)se2->string; | |
2337 | |
2338 for (u = 0; u < len; u++) | |
2339 { | |
2340 if (s1[u] != s2[u]) | |
2341 return s1[u] - s2[u]; | |
2342 } | |
2343 } | |
2344 | |
2345 case 4: | |
2346 { unsigned u; | |
2347 d_dchar *s1 = (d_dchar *)string; | |
2348 d_dchar *s2 = (d_dchar *)se2->string; | |
2349 | |
2350 for (u = 0; u < len; u++) | |
2351 { | |
2352 if (s1[u] != s2[u]) | |
2353 return s1[u] - s2[u]; | |
2354 } | |
2355 } | |
2356 break; | |
2357 | |
2358 default: | |
2359 assert(0); | |
2360 } | |
2361 } | |
2362 return len1 - len2; | |
2363 } | |
2364 | |
2365 int StringExp::isBool(int result) | |
2366 { | |
2367 return result ? TRUE : FALSE; | |
2368 } | |
2369 | |
2370 unsigned StringExp::charAt(size_t i) | |
2371 { unsigned value; | |
2372 | |
2373 switch (sz) | |
2374 { | |
2375 case 1: | |
2376 value = ((unsigned char *)string)[i]; | |
2377 break; | |
2378 | |
2379 case 2: | |
2380 value = ((unsigned short *)string)[i]; | |
2381 break; | |
2382 | |
2383 case 4: | |
2384 value = ((unsigned int *)string)[i]; | |
2385 break; | |
2386 | |
2387 default: | |
2388 assert(0); | |
2389 break; | |
2390 } | |
2391 return value; | |
2392 } | |
2393 | |
2394 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2395 { | |
2396 buf->writeByte('"'); | |
2397 for (size_t i = 0; i < len; i++) | |
2398 { unsigned c = charAt(i); | |
2399 | |
2400 switch (c) | |
2401 { | |
2402 case '"': | |
2403 case '\\': | |
2404 if (!hgs->console) | |
2405 buf->writeByte('\\'); | |
2406 default: | |
2407 if (c <= 0xFF) | |
2408 { if (c <= 0x7F && (isprint(c) || hgs->console)) | |
2409 buf->writeByte(c); | |
2410 else | |
2411 buf->printf("\\x%02x", c); | |
2412 } | |
2413 else if (c <= 0xFFFF) | |
2414 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8); | |
2415 else | |
2416 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x", | |
2417 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24); | |
2418 break; | |
2419 } | |
2420 } | |
2421 buf->writeByte('"'); | |
2422 if (postfix) | |
2423 buf->writeByte(postfix); | |
2424 } | |
2425 | |
2426 void StringExp::toMangleBuffer(OutBuffer *buf) | |
2427 { char m; | |
2428 OutBuffer tmp; | |
2429 char *p; | |
2430 unsigned c; | |
2431 size_t u; | |
2432 unsigned char *q; | |
2433 unsigned qlen; | |
2434 | |
2435 /* Write string in UTF-8 format | |
2436 */ | |
2437 switch (sz) | |
2438 { case 1: | |
2439 m = 'a'; | |
2440 q = (unsigned char *)string; | |
2441 qlen = len; | |
2442 break; | |
2443 case 2: | |
2444 m = 'w'; | |
2445 for (u = 0; u < len; ) | |
2446 { | |
2447 p = utf_decodeWchar((unsigned short *)string, len, &u, &c); | |
2448 if (p) | |
2449 error("%s", p); | |
2450 else | |
2451 tmp.writeUTF8(c); | |
2452 } | |
2453 q = tmp.data; | |
2454 qlen = tmp.offset; | |
2455 break; | |
2456 case 4: | |
2457 m = 'd'; | |
2458 for (u = 0; u < len; u++) | |
2459 { | |
2460 c = ((unsigned *)string)[u]; | |
2461 if (!utf_isValidDchar(c)) | |
2462 error("invalid UCS-32 char \\U%08x", c); | |
2463 else | |
2464 tmp.writeUTF8(c); | |
2465 } | |
2466 q = tmp.data; | |
2467 qlen = tmp.offset; | |
2468 break; | |
2469 default: | |
2470 assert(0); | |
2471 } | |
2472 buf->writeByte(m); | |
2473 buf->printf("%d_", qlen); | |
2474 for (size_t i = 0; i < qlen; i++) | |
2475 buf->printf("%02x", q[i]); | |
2476 } | |
2477 | |
2478 /************************ ArrayLiteralExp ************************************/ | |
2479 | |
2480 // [ e1, e2, e3, ... ] | |
2481 | |
2482 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements) | |
2483 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2484 { | |
2485 this->elements = elements; | |
2486 } | |
2487 | |
2488 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) | |
2489 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2490 { | |
2491 elements = new Expressions; | |
2492 elements->push(e); | |
2493 } | |
2494 | |
2495 Expression *ArrayLiteralExp::syntaxCopy() | |
2496 { | |
2497 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); | |
2498 } | |
2499 | |
2500 Expression *ArrayLiteralExp::semantic(Scope *sc) | |
2501 { Expression *e; | |
2502 Type *t0 = NULL; | |
2503 | |
2504 #if LOGSEMANTIC | |
2505 printf("ArrayLiteralExp::semantic('%s')\n", toChars()); | |
2506 #endif | |
2507 if (type) | |
2508 return this; | |
2509 | |
2510 // Run semantic() on each element | |
2511 for (int i = 0; i < elements->dim; i++) | |
2512 { e = (Expression *)elements->data[i]; | |
2513 e = e->semantic(sc); | |
2514 elements->data[i] = (void *)e; | |
2515 } | |
2516 expandTuples(elements); | |
2517 for (int i = 0; i < elements->dim; i++) | |
2518 { e = (Expression *)elements->data[i]; | |
2519 | |
2520 if (!e->type) | |
2521 error("%s has no value", e->toChars()); | |
2522 e = resolveProperties(sc, e); | |
2523 | |
2524 unsigned char committed = 1; | |
2525 if (e->op == TOKstring) | |
2526 committed = ((StringExp *)e)->committed; | |
2527 | |
2528 if (!t0) | |
2529 { t0 = e->type; | |
2530 // Convert any static arrays to dynamic arrays | |
2531 if (t0->ty == Tsarray) | |
2532 { | |
2533 t0 = t0->next->arrayOf(); | |
2534 e = e->implicitCastTo(sc, t0); | |
2535 } | |
2536 } | |
2537 else | |
2538 e = e->implicitCastTo(sc, t0); | |
2539 if (!committed && e->op == TOKstring) | |
2540 { StringExp *se = (StringExp *)e; | |
2541 se->committed = 0; | |
2542 } | |
2543 elements->data[i] = (void *)e; | |
2544 } | |
2545 | |
2546 if (!t0) | |
2547 t0 = Type::tvoid; | |
2548 type = new TypeSArray(t0, new IntegerExp(elements->dim)); | |
2549 type = type->semantic(loc, sc); | |
2550 return this; | |
2551 } | |
2552 | |
2553 int ArrayLiteralExp::checkSideEffect(int flag) | |
2554 { int f = 0; | |
2555 | |
2556 for (size_t i = 0; i < elements->dim; i++) | |
2557 { Expression *e = (Expression *)elements->data[i]; | |
2558 | |
2559 f |= e->checkSideEffect(2); | |
2560 } | |
2561 if (flag == 0 && f == 0) | |
2562 Expression::checkSideEffect(0); | |
2563 return f; | |
2564 } | |
2565 | |
2566 int ArrayLiteralExp::isBool(int result) | |
2567 { | |
2568 size_t dim = elements ? elements->dim : 0; | |
2569 return result ? (dim != 0) : (dim == 0); | |
2570 } | |
2571 | |
2572 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2573 { | |
2574 buf->writeByte('['); | |
2575 argsToCBuffer(buf, elements, hgs); | |
2576 buf->writeByte(']'); | |
2577 } | |
2578 | |
2579 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2580 { | |
2581 size_t dim = elements ? elements->dim : 0; | |
2582 buf->printf("A%u", dim); | |
2583 for (size_t i = 0; i < dim; i++) | |
2584 { Expression *e = (Expression *)elements->data[i]; | |
2585 e->toMangleBuffer(buf); | |
2586 } | |
2587 } | |
2588 | |
2589 /************************ AssocArrayLiteralExp ************************************/ | |
2590 | |
2591 // [ key0 : value0, key1 : value1, ... ] | |
2592 | |
2593 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, | |
2594 Expressions *keys, Expressions *values) | |
2595 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp)) | |
2596 { | |
2597 assert(keys->dim == values->dim); | |
2598 this->keys = keys; | |
2599 this->values = values; | |
2600 } | |
2601 | |
2602 Expression *AssocArrayLiteralExp::syntaxCopy() | |
2603 { | |
2604 return new AssocArrayLiteralExp(loc, | |
2605 arraySyntaxCopy(keys), arraySyntaxCopy(values)); | |
2606 } | |
2607 | |
2608 Expression *AssocArrayLiteralExp::semantic(Scope *sc) | |
2609 { Expression *e; | |
2610 Type *tkey = NULL; | |
2611 Type *tvalue = NULL; | |
2612 | |
2613 #if LOGSEMANTIC | |
2614 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); | |
2615 #endif | |
2616 | |
2617 // Run semantic() on each element | |
2618 for (size_t i = 0; i < keys->dim; i++) | |
2619 { Expression *key = (Expression *)keys->data[i]; | |
2620 Expression *value = (Expression *)values->data[i]; | |
2621 | |
2622 key = key->semantic(sc); | |
2623 value = value->semantic(sc); | |
2624 | |
2625 keys->data[i] = (void *)key; | |
2626 values->data[i] = (void *)value; | |
2627 } | |
2628 expandTuples(keys); | |
2629 expandTuples(values); | |
2630 if (keys->dim != values->dim) | |
2631 { | |
2632 error("number of keys is %u, must match number of values %u", keys->dim, values->dim); | |
2633 keys->setDim(0); | |
2634 values->setDim(0); | |
2635 } | |
2636 for (size_t i = 0; i < keys->dim; i++) | |
2637 { Expression *key = (Expression *)keys->data[i]; | |
2638 Expression *value = (Expression *)values->data[i]; | |
2639 | |
2640 if (!key->type) | |
2641 error("%s has no value", key->toChars()); | |
2642 if (!value->type) | |
2643 error("%s has no value", value->toChars()); | |
2644 key = resolveProperties(sc, key); | |
2645 value = resolveProperties(sc, value); | |
2646 | |
2647 if (!tkey) | |
2648 tkey = key->type; | |
2649 else | |
2650 key = key->implicitCastTo(sc, tkey); | |
2651 keys->data[i] = (void *)key; | |
2652 | |
2653 if (!tvalue) | |
2654 tvalue = value->type; | |
2655 else | |
2656 value = value->implicitCastTo(sc, tvalue); | |
2657 values->data[i] = (void *)value; | |
2658 } | |
2659 | |
2660 if (!tkey) | |
2661 tkey = Type::tvoid; | |
2662 if (!tvalue) | |
2663 tvalue = Type::tvoid; | |
2664 type = new TypeAArray(tvalue, tkey); | |
2665 type = type->semantic(loc, sc); | |
2666 return this; | |
2667 } | |
2668 | |
2669 int AssocArrayLiteralExp::checkSideEffect(int flag) | |
2670 { int f = 0; | |
2671 | |
2672 for (size_t i = 0; i < keys->dim; i++) | |
2673 { Expression *key = (Expression *)keys->data[i]; | |
2674 Expression *value = (Expression *)values->data[i]; | |
2675 | |
2676 f |= key->checkSideEffect(2); | |
2677 f |= value->checkSideEffect(2); | |
2678 } | |
2679 if (flag == 0 && f == 0) | |
2680 Expression::checkSideEffect(0); | |
2681 return f; | |
2682 } | |
2683 | |
2684 int AssocArrayLiteralExp::isBool(int result) | |
2685 { | |
2686 size_t dim = keys->dim; | |
2687 return result ? (dim != 0) : (dim == 0); | |
2688 } | |
2689 | |
2690 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2691 { | |
2692 buf->writeByte('['); | |
2693 for (size_t i = 0; i < keys->dim; i++) | |
2694 { Expression *key = (Expression *)keys->data[i]; | |
2695 Expression *value = (Expression *)values->data[i]; | |
2696 | |
2697 if (i) | |
2698 buf->writeByte(','); | |
2699 expToCBuffer(buf, hgs, key, PREC_assign); | |
2700 buf->writeByte(':'); | |
2701 expToCBuffer(buf, hgs, value, PREC_assign); | |
2702 } | |
2703 buf->writeByte(']'); | |
2704 } | |
2705 | |
2706 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2707 { | |
2708 size_t dim = keys->dim; | |
2709 buf->printf("A%u", dim); | |
2710 for (size_t i = 0; i < dim; i++) | |
2711 { Expression *key = (Expression *)keys->data[i]; | |
2712 Expression *value = (Expression *)values->data[i]; | |
2713 | |
2714 key->toMangleBuffer(buf); | |
2715 value->toMangleBuffer(buf); | |
2716 } | |
2717 } | |
2718 | |
2719 /************************ StructLiteralExp ************************************/ | |
2720 | |
2721 // sd( e1, e2, e3, ... ) | |
2722 | |
2723 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements) | |
2724 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) | |
2725 { | |
2726 this->sd = sd; | |
2727 this->elements = elements; | |
2728 this->sym = NULL; | |
2729 this->soffset = 0; | |
2730 this->fillHoles = 1; | |
2731 } | |
2732 | |
2733 Expression *StructLiteralExp::syntaxCopy() | |
2734 { | |
2735 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); | |
2736 } | |
2737 | |
2738 Expression *StructLiteralExp::semantic(Scope *sc) | |
2739 { Expression *e; | |
2740 | |
2741 #if LOGSEMANTIC | |
2742 printf("StructLiteralExp::semantic('%s')\n", toChars()); | |
2743 #endif | |
2744 | |
2745 // Run semantic() on each element | |
2746 for (size_t i = 0; i < elements->dim; i++) | |
2747 { e = (Expression *)elements->data[i]; | |
2748 if (!e) | |
2749 continue; | |
2750 e = e->semantic(sc); | |
2751 elements->data[i] = (void *)e; | |
2752 } | |
2753 expandTuples(elements); | |
2754 size_t offset = 0; | |
2755 for (size_t i = 0; i < elements->dim; i++) | |
2756 { e = (Expression *)elements->data[i]; | |
2757 if (!e) | |
2758 continue; | |
2759 | |
2760 if (!e->type) | |
2761 error("%s has no value", e->toChars()); | |
2762 e = resolveProperties(sc, e); | |
2763 if (i >= sd->fields.dim) | |
2764 { error("more initializers than fields of %s", sd->toChars()); | |
2765 break; | |
2766 } | |
2767 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
2768 VarDeclaration *v = s->isVarDeclaration(); | |
2769 assert(v); | |
2770 if (v->offset < offset) | |
2771 error("overlapping initialization for %s", v->toChars()); | |
2772 offset = v->offset + v->type->size(); | |
2773 | |
2774 Type *telem = v->type; | |
2775 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray) | |
2776 { /* Static array initialization, as in: | |
2777 * T[3][5] = e; | |
2778 */ | |
2779 telem = telem->toBasetype()->nextOf(); | |
2780 } | |
2781 | |
2782 e = e->implicitCastTo(sc, telem); | |
2783 | |
2784 elements->data[i] = (void *)e; | |
2785 } | |
2786 | |
2787 /* Fill out remainder of elements[] with default initializers for fields[] | |
2788 */ | |
2789 for (size_t i = elements->dim; i < sd->fields.dim; i++) | |
2790 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
2791 VarDeclaration *v = s->isVarDeclaration(); | |
2792 assert(v); | |
2793 | |
2794 if (v->offset < offset) | |
2795 { e = NULL; | |
2796 sd->hasUnions = 1; | |
2797 } | |
2798 else | |
2799 { | |
2800 if (v->init) | |
2801 { e = v->init->toExpression(); | |
2802 if (!e) | |
2803 error("cannot make expression out of initializer for %s", v->toChars()); | |
2804 } | |
2805 else | |
2806 { e = v->type->defaultInit(); | |
2807 e->loc = loc; | |
2808 } | |
2809 offset = v->offset + v->type->size(); | |
2810 } | |
2811 elements->push(e); | |
2812 } | |
2813 | |
2814 type = sd->type; | |
2815 return this; | |
2816 } | |
2817 | |
2818 /************************************** | |
2819 * Gets expression at offset of type. | |
2820 * Returns NULL if not found. | |
2821 */ | |
2822 | |
2823 Expression *StructLiteralExp::getField(Type *type, unsigned offset) | |
2824 { Expression *e = NULL; | |
2825 int i = getFieldIndex(type, offset); | |
2826 | |
2827 if (i != -1) | |
2828 { e = (Expression *)elements->data[i]; | |
2829 if (e) | |
2830 { | |
2831 e = e->copy(); | |
2832 e->type = type; | |
2833 } | |
2834 } | |
2835 return e; | |
2836 } | |
2837 | |
2838 /************************************ | |
2839 * Get index of field. | |
2840 * Returns -1 if not found. | |
2841 */ | |
2842 | |
2843 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) | |
2844 { | |
2845 /* Find which field offset is by looking at the field offsets | |
2846 */ | |
2847 for (size_t i = 0; i < sd->fields.dim; i++) | |
2848 { | |
2849 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
2850 VarDeclaration *v = s->isVarDeclaration(); | |
2851 assert(v); | |
2852 | |
2853 if (offset == v->offset && | |
2854 type->size() == v->type->size()) | |
2855 { Expression *e = (Expression *)elements->data[i]; | |
2856 if (e) | |
2857 { | |
2858 return i; | |
2859 } | |
2860 break; | |
2861 } | |
2862 } | |
2863 return -1; | |
2864 } | |
2865 | |
2866 | |
2867 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) | |
2868 { | |
2869 return this; | |
2870 } | |
2871 | |
2872 | |
2873 int StructLiteralExp::checkSideEffect(int flag) | |
2874 { int f = 0; | |
2875 | |
2876 for (size_t i = 0; i < elements->dim; i++) | |
2877 { Expression *e = (Expression *)elements->data[i]; | |
2878 if (!e) | |
2879 continue; | |
2880 | |
2881 f |= e->checkSideEffect(2); | |
2882 } | |
2883 if (flag == 0 && f == 0) | |
2884 Expression::checkSideEffect(0); | |
2885 return f; | |
2886 } | |
2887 | |
2888 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2889 { | |
2890 buf->writestring(sd->toChars()); | |
2891 buf->writeByte('('); | |
2892 argsToCBuffer(buf, elements, hgs); | |
2893 buf->writeByte(')'); | |
2894 } | |
2895 | |
2896 void StructLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2897 { | |
2898 size_t dim = elements ? elements->dim : 0; | |
2899 buf->printf("S%u", dim); | |
2900 for (size_t i = 0; i < dim; i++) | |
2901 { Expression *e = (Expression *)elements->data[i]; | |
2902 if (e) | |
2903 e->toMangleBuffer(buf); | |
2904 else | |
2905 buf->writeByte('v'); // 'v' for void | |
2906 } | |
2907 } | |
2908 | |
2909 /************************ TypeDotIdExp ************************************/ | |
2910 | |
2911 /* Things like: | |
2912 * int.size | |
2913 * foo.size | |
2914 * (foo).size | |
2915 * cast(foo).size | |
2916 */ | |
2917 | |
2918 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident) | |
2919 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp)) | |
2920 { | |
2921 this->type = type; | |
2922 this->ident = ident; | |
2923 } | |
2924 | |
2925 Expression *TypeDotIdExp::syntaxCopy() | |
2926 { | |
2927 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident); | |
2928 return te; | |
2929 } | |
2930 | |
2931 Expression *TypeDotIdExp::semantic(Scope *sc) | |
2932 { Expression *e; | |
2933 | |
2934 #if LOGSEMANTIC | |
2935 printf("TypeDotIdExp::semantic()\n"); | |
2936 #endif | |
2937 e = new DotIdExp(loc, new TypeExp(loc, type), ident); | |
2938 e = e->semantic(sc); | |
2939 return e; | |
2940 } | |
2941 | |
2942 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2943 { | |
2944 buf->writeByte('('); | |
2945 type->toCBuffer(buf, NULL, hgs); | |
2946 buf->writeByte(')'); | |
2947 buf->writeByte('.'); | |
2948 buf->writestring(ident->toChars()); | |
2949 } | |
2950 | |
2951 /************************************************************/ | |
2952 | |
2953 // Mainly just a placeholder | |
2954 | |
2955 TypeExp::TypeExp(Loc loc, Type *type) | |
2956 : Expression(loc, TOKtype, sizeof(TypeExp)) | |
2957 { | |
2958 //printf("TypeExp::TypeExp(%s)\n", type->toChars()); | |
2959 this->type = type; | |
2960 } | |
2961 | |
2962 Expression *TypeExp::semantic(Scope *sc) | |
2963 { | |
2964 //printf("TypeExp::semantic(%s)\n", type->toChars()); | |
2965 type = type->semantic(loc, sc); | |
2966 return this; | |
2967 } | |
2968 | |
2969 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2970 { | |
2971 type->toCBuffer(buf, NULL, hgs); | |
2972 } | |
2973 | |
2974 /************************************************************/ | |
2975 | |
2976 // Mainly just a placeholder | |
2977 | |
2978 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg) | |
2979 : Expression(loc, TOKimport, sizeof(ScopeExp)) | |
2980 { | |
2981 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars()); | |
2982 //static int count; if (++count == 38) *(char*)0=0; | |
2983 this->sds = pkg; | |
2984 } | |
2985 | |
2986 Expression *ScopeExp::syntaxCopy() | |
2987 { | |
2988 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL)); | |
2989 return se; | |
2990 } | |
2991 | |
2992 Expression *ScopeExp::semantic(Scope *sc) | |
2993 { | |
2994 TemplateInstance *ti; | |
2995 ScopeDsymbol *sds2; | |
2996 | |
2997 #if LOGSEMANTIC | |
2998 printf("+ScopeExp::semantic('%s')\n", toChars()); | |
2999 #endif | |
3000 Lagain: | |
3001 ti = sds->isTemplateInstance(); | |
3002 if (ti && !global.errors) | |
3003 { Dsymbol *s; | |
3004 if (!ti->semanticdone) | |
3005 ti->semantic(sc); | |
3006 s = ti->inst->toAlias(); | |
3007 sds2 = s->isScopeDsymbol(); | |
3008 if (!sds2) | |
3009 { Expression *e; | |
3010 | |
3011 //printf("s = %s, '%s'\n", s->kind(), s->toChars()); | |
3012 if (ti->withsym) | |
3013 { | |
3014 // Same as wthis.s | |
3015 e = new VarExp(loc, ti->withsym->withstate->wthis); | |
3016 e = new DotVarExp(loc, e, s->isDeclaration()); | |
3017 } | |
3018 else | |
3019 e = new DsymbolExp(loc, s); | |
3020 e = e->semantic(sc); | |
3021 //printf("-1ScopeExp::semantic()\n"); | |
3022 return e; | |
3023 } | |
3024 if (sds2 != sds) | |
3025 { | |
3026 sds = sds2; | |
3027 goto Lagain; | |
3028 } | |
3029 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3030 } | |
3031 else | |
3032 { | |
3033 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3034 //printf("\tparent = '%s'\n", sds->parent->toChars()); | |
3035 sds->semantic(sc); | |
3036 } | |
3037 type = Type::tvoid; | |
3038 //printf("-2ScopeExp::semantic() %s\n", toChars()); | |
3039 return this; | |
3040 } | |
3041 | |
3042 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3043 { | |
3044 if (sds->isTemplateInstance()) | |
3045 { | |
3046 sds->toCBuffer(buf, hgs); | |
3047 } | |
3048 else | |
3049 { | |
3050 buf->writestring(sds->kind()); | |
3051 buf->writestring(" "); | |
3052 buf->writestring(sds->toChars()); | |
3053 } | |
3054 } | |
3055 | |
3056 /********************** TemplateExp **************************************/ | |
3057 | |
3058 // Mainly just a placeholder | |
3059 | |
3060 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td) | |
3061 : Expression(loc, TOKtemplate, sizeof(TemplateExp)) | |
3062 { | |
3063 //printf("TemplateExp(): %s\n", td->toChars()); | |
3064 this->td = td; | |
3065 } | |
3066 | |
3067 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3068 { | |
3069 buf->writestring(td->toChars()); | |
3070 } | |
3071 | |
3072 void TemplateExp::rvalue() | |
3073 { | |
3074 error("template %s has no value", toChars()); | |
3075 } | |
3076 | |
3077 /********************** NewExp **************************************/ | |
3078 | |
3079 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs, | |
3080 Type *newtype, Expressions *arguments) | |
3081 : Expression(loc, TOKnew, sizeof(NewExp)) | |
3082 { | |
3083 this->thisexp = thisexp; | |
3084 this->newargs = newargs; | |
3085 this->newtype = newtype; | |
3086 this->arguments = arguments; | |
3087 member = NULL; | |
3088 allocator = NULL; | |
3089 onstack = 0; | |
3090 } | |
3091 | |
3092 Expression *NewExp::syntaxCopy() | |
3093 { | |
3094 return new NewExp(loc, | |
3095 thisexp ? thisexp->syntaxCopy() : NULL, | |
3096 arraySyntaxCopy(newargs), | |
3097 newtype->syntaxCopy(), arraySyntaxCopy(arguments)); | |
3098 } | |
3099 | |
3100 | |
3101 Expression *NewExp::semantic(Scope *sc) | |
3102 { int i; | |
3103 Type *tb; | |
3104 ClassDeclaration *cdthis = NULL; | |
3105 | |
3106 #if LOGSEMANTIC | |
3107 printf("NewExp::semantic() %s\n", toChars()); | |
3108 if (thisexp) | |
3109 printf("\tthisexp = %s\n", thisexp->toChars()); | |
3110 printf("\tnewtype: %s\n", newtype->toChars()); | |
3111 #endif | |
3112 if (type) // if semantic() already run | |
3113 return this; | |
3114 | |
3115 Lagain: | |
3116 if (thisexp) | |
3117 { thisexp = thisexp->semantic(sc); | |
3118 cdthis = thisexp->type->isClassHandle(); | |
3119 if (cdthis) | |
3120 { | |
3121 sc = sc->push(cdthis); | |
3122 type = newtype->semantic(loc, sc); | |
3123 sc = sc->pop(); | |
3124 } | |
3125 else | |
3126 { | |
3127 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars()); | |
3128 type = newtype->semantic(loc, sc); | |
3129 } | |
3130 } | |
3131 else | |
3132 type = newtype->semantic(loc, sc); | |
3133 newtype = type; // in case type gets cast to something else | |
3134 tb = type->toBasetype(); | |
3135 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); | |
3136 | |
3137 arrayExpressionSemantic(newargs, sc); | |
3138 preFunctionArguments(loc, sc, newargs); | |
3139 arrayExpressionSemantic(arguments, sc); | |
3140 preFunctionArguments(loc, sc, arguments); | |
3141 | |
3142 if (thisexp && tb->ty != Tclass) | |
3143 error("e.new is only for allocating nested classes, not %s", tb->toChars()); | |
3144 | |
3145 if (tb->ty == Tclass) | |
3146 { TypeFunction *tf; | |
3147 | |
3148 TypeClass *tc = (TypeClass *)(tb); | |
3149 ClassDeclaration *cd = tc->sym->isClassDeclaration(); | |
3150 if (cd->isInterfaceDeclaration()) | |
3151 error("cannot create instance of interface %s", cd->toChars()); | |
3152 else if (cd->isAbstract()) | |
3153 { error("cannot create instance of abstract class %s", cd->toChars()); | |
3154 for (int i = 0; i < cd->vtbl.dim; i++) | |
3155 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration(); | |
3156 if (fd && fd->isAbstract()) | |
3157 error("function %s is abstract", fd->toChars()); | |
3158 } | |
3159 } | |
3160 checkDeprecated(sc, cd); | |
3161 if (cd->isNested()) | |
3162 { /* We need a 'this' pointer for the nested class. | |
3163 * Ensure we have the right one. | |
3164 */ | |
3165 Dsymbol *s = cd->toParent2(); | |
3166 ClassDeclaration *cdn = s->isClassDeclaration(); | |
3167 | |
3168 //printf("isNested, cdn = %s\n", cdn ? cdn->toChars() : "null"); | |
3169 if (cdn) | |
3170 { | |
3171 if (!cdthis) | |
3172 { | |
3173 // Supply an implicit 'this' and try again | |
3174 thisexp = new ThisExp(loc); | |
3175 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) | |
3176 { if (!sp) | |
3177 { | |
3178 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3179 break; | |
3180 } | |
3181 ClassDeclaration *cdp = sp->isClassDeclaration(); | |
3182 if (!cdp) | |
3183 continue; | |
3184 if (cdp == cdn || cdn->isBaseOf(cdp, NULL)) | |
3185 break; | |
3186 // Add a '.outer' and try again | |
3187 thisexp = new DotIdExp(loc, thisexp, Id::outer); | |
3188 } | |
3189 if (!global.errors) | |
3190 goto Lagain; | |
3191 } | |
3192 if (cdthis) | |
3193 { | |
3194 //printf("cdthis = %s\n", cdthis->toChars()); | |
3195 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL)) | |
3196 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars()); | |
3197 } | |
3198 #if 0 | |
3199 else | |
3200 { | |
3201 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration()) | |
3202 { | |
3203 if (!sf) | |
3204 { | |
3205 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3206 break; | |
3207 } | |
3208 printf("sf = %s\n", sf->toChars()); | |
3209 AggregateDeclaration *ad = sf->isThis(); | |
3210 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL))) | |
3211 break; | |
3212 } | |
3213 } | |
3214 #endif | |
3215 } | |
3216 else if (thisexp) | |
3217 error("e.new is only for allocating nested classes"); | |
3218 } | |
3219 else if (thisexp) | |
3220 error("e.new is only for allocating nested classes"); | |
3221 | |
3222 FuncDeclaration *f = cd->ctor; | |
3223 if (f) | |
3224 { | |
3225 assert(f); | |
3226 f = f->overloadResolve(loc, arguments); | |
3227 checkDeprecated(sc, f); | |
3228 member = f->isCtorDeclaration(); | |
3229 assert(member); | |
3230 | |
3231 cd->accessCheck(loc, sc, member); | |
3232 | |
3233 tf = (TypeFunction *)f->type; | |
3234 type = tf->next; | |
3235 | |
3236 if (!arguments) | |
3237 arguments = new Expressions(); | |
3238 functionArguments(loc, sc, tf, arguments); | |
3239 } | |
3240 else | |
3241 { | |
3242 if (arguments && arguments->dim) | |
3243 error("no constructor for %s", cd->toChars()); | |
3244 } | |
3245 | |
3246 if (cd->aggNew) | |
3247 { Expression *e; | |
3248 | |
3249 f = cd->aggNew; | |
3250 | |
3251 // Prepend the uint size argument to newargs[] | |
3252 e = new IntegerExp(loc, cd->size(loc), Type::tuns32); | |
3253 if (!newargs) | |
3254 newargs = new Expressions(); | |
3255 newargs->shift(e); | |
3256 | |
3257 f = f->overloadResolve(loc, newargs); | |
3258 allocator = f->isNewDeclaration(); | |
3259 assert(allocator); | |
3260 | |
3261 tf = (TypeFunction *)f->type; | |
3262 functionArguments(loc, sc, tf, newargs); | |
3263 } | |
3264 else | |
3265 { | |
3266 if (newargs && newargs->dim) | |
3267 error("no allocator for %s", cd->toChars()); | |
3268 } | |
3269 | |
3270 } | |
3271 else if (tb->ty == Tstruct) | |
3272 { | |
3273 TypeStruct *ts = (TypeStruct *)tb; | |
3274 StructDeclaration *sd = ts->sym; | |
3275 FuncDeclaration *f = sd->aggNew; | |
3276 TypeFunction *tf; | |
3277 | |
3278 if (arguments && arguments->dim) | |
3279 error("no constructor for %s", type->toChars()); | |
3280 | |
3281 if (f) | |
3282 { | |
3283 Expression *e; | |
3284 | |
3285 // Prepend the uint size argument to newargs[] | |
3286 e = new IntegerExp(loc, sd->size(loc), Type::tuns32); | |
3287 if (!newargs) | |
3288 newargs = new Expressions(); | |
3289 newargs->shift(e); | |
3290 | |
3291 f = f->overloadResolve(loc, newargs); | |
3292 allocator = f->isNewDeclaration(); | |
3293 assert(allocator); | |
3294 | |
3295 tf = (TypeFunction *)f->type; | |
3296 functionArguments(loc, sc, tf, newargs); | |
3297 | |
3298 e = new VarExp(loc, f); | |
3299 e = new CallExp(loc, e, newargs); | |
3300 e = e->semantic(sc); | |
3301 e->type = type->pointerTo(); | |
3302 return e; | |
3303 } | |
3304 | |
3305 type = type->pointerTo(); | |
3306 } | |
3307 else if (tb->ty == Tarray && (arguments && arguments->dim)) | |
3308 { | |
3309 for (size_t i = 0; i < arguments->dim; i++) | |
3310 { | |
3311 if (tb->ty != Tarray) | |
3312 { error("too many arguments for array"); | |
3313 arguments->dim = i; | |
3314 break; | |
3315 } | |
3316 | |
3317 Expression *arg = (Expression *)arguments->data[i]; | |
3318 arg = resolveProperties(sc, arg); | |
3319 arg = arg->implicitCastTo(sc, Type::tsize_t); | |
3320 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) | |
3321 error("negative array index %s", arg->toChars()); | |
3322 arguments->data[i] = (void *) arg; | |
3323 tb = tb->next->toBasetype(); | |
3324 } | |
3325 } | |
3326 else if (tb->isscalar()) | |
3327 { | |
3328 if (arguments && arguments->dim) | |
3329 error("no constructor for %s", type->toChars()); | |
3330 | |
3331 type = type->pointerTo(); | |
3332 } | |
3333 else | |
3334 { | |
3335 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars()); | |
3336 type = type->pointerTo(); | |
3337 } | |
3338 | |
3339 //printf("NewExp: '%s'\n", toChars()); | |
3340 //printf("NewExp:type '%s'\n", type->toChars()); | |
3341 | |
3342 return this; | |
3343 } | |
3344 | |
3345 int NewExp::checkSideEffect(int flag) | |
3346 { | |
3347 return 1; | |
3348 } | |
3349 | |
3350 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3351 { int i; | |
3352 | |
3353 if (thisexp) | |
3354 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3355 buf->writeByte('.'); | |
3356 } | |
3357 buf->writestring("new "); | |
3358 if (newargs && newargs->dim) | |
3359 { | |
3360 buf->writeByte('('); | |
3361 argsToCBuffer(buf, newargs, hgs); | |
3362 buf->writeByte(')'); | |
3363 } | |
3364 newtype->toCBuffer(buf, NULL, hgs); | |
3365 if (arguments && arguments->dim) | |
3366 { | |
3367 buf->writeByte('('); | |
3368 argsToCBuffer(buf, arguments, hgs); | |
3369 buf->writeByte(')'); | |
3370 } | |
3371 } | |
3372 | |
3373 /********************** NewAnonClassExp **************************************/ | |
3374 | |
3375 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp, | |
3376 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments) | |
3377 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp)) | |
3378 { | |
3379 this->thisexp = thisexp; | |
3380 this->newargs = newargs; | |
3381 this->cd = cd; | |
3382 this->arguments = arguments; | |
3383 } | |
3384 | |
3385 Expression *NewAnonClassExp::syntaxCopy() | |
3386 { | |
3387 return new NewAnonClassExp(loc, | |
3388 thisexp ? thisexp->syntaxCopy() : NULL, | |
3389 arraySyntaxCopy(newargs), | |
3390 (ClassDeclaration *)cd->syntaxCopy(NULL), | |
3391 arraySyntaxCopy(arguments)); | |
3392 } | |
3393 | |
3394 | |
3395 Expression *NewAnonClassExp::semantic(Scope *sc) | |
3396 { | |
3397 #if LOGSEMANTIC | |
3398 printf("NewAnonClassExp::semantic() %s\n", toChars()); | |
3399 //printf("type: %s\n", type->toChars()); | |
3400 #endif | |
3401 | |
3402 Expression *d = new DeclarationExp(loc, cd); | |
3403 d = d->semantic(sc); | |
3404 | |
3405 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments); | |
3406 | |
3407 Expression *c = new CommaExp(loc, d, n); | |
3408 return c->semantic(sc); | |
3409 } | |
3410 | |
3411 int NewAnonClassExp::checkSideEffect(int flag) | |
3412 { | |
3413 return 1; | |
3414 } | |
3415 | |
3416 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3417 { int i; | |
3418 | |
3419 if (thisexp) | |
3420 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3421 buf->writeByte('.'); | |
3422 } | |
3423 buf->writestring("new"); | |
3424 if (newargs && newargs->dim) | |
3425 { | |
3426 buf->writeByte('('); | |
3427 argsToCBuffer(buf, newargs, hgs); | |
3428 buf->writeByte(')'); | |
3429 } | |
3430 buf->writestring(" class "); | |
3431 if (arguments && arguments->dim) | |
3432 { | |
3433 buf->writeByte('('); | |
3434 argsToCBuffer(buf, arguments, hgs); | |
3435 buf->writeByte(')'); | |
3436 } | |
3437 //buf->writestring(" { }"); | |
3438 if (cd) | |
3439 { | |
3440 cd->toCBuffer(buf, hgs); | |
3441 } | |
3442 } | |
3443 | |
3444 /********************** SymOffExp **************************************/ | |
3445 | |
3446 SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset) | |
3447 : Expression(loc, TOKsymoff, sizeof(SymOffExp)) | |
3448 { | |
3449 assert(var); | |
3450 this->var = var; | |
3451 this->offset = offset; | |
3452 VarDeclaration *v = var->isVarDeclaration(); | |
3453 if (v && v->needThis()) | |
3454 error("need 'this' for address of %s", v->toChars()); | |
3455 } | |
3456 | |
3457 Expression *SymOffExp::semantic(Scope *sc) | |
3458 { | |
3459 #if LOGSEMANTIC | |
3460 printf("SymOffExp::semantic('%s')\n", toChars()); | |
3461 #endif | |
3462 //var->semantic(sc); | |
3463 if (!type) | |
3464 type = var->type->pointerTo(); | |
3465 VarDeclaration *v = var->isVarDeclaration(); | |
3466 if (v) | |
3467 { | |
3468 v->checkNestedReference(sc, loc); | |
3469 v->needsStorage = true; | |
3470 } | |
3471 return this; | |
3472 } | |
3473 | |
3474 int SymOffExp::isBool(int result) | |
3475 { | |
3476 return result ? TRUE : FALSE; | |
3477 } | |
3478 | |
3479 void SymOffExp::checkEscape() | |
3480 { | |
3481 VarDeclaration *v = var->isVarDeclaration(); | |
3482 if (v) | |
3483 { | |
3484 if (!v->isDataseg()) | |
3485 error("escaping reference to local variable %s", v->toChars()); | |
3486 } | |
3487 } | |
3488 | |
3489 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3490 { | |
3491 if (offset) | |
3492 buf->printf("(& %s+%u)", var->toChars(), offset); | |
3493 else | |
3494 buf->printf("& %s", var->toChars()); | |
3495 } | |
3496 | |
3497 /******************************** VarExp **************************/ | |
3498 | |
3499 VarExp::VarExp(Loc loc, Declaration *var) | |
3500 : Expression(loc, TOKvar, sizeof(VarExp)) | |
3501 { | |
3502 //printf("VarExp(this = %p, '%s')\n", this, var->toChars()); | |
3503 this->var = var; | |
3504 this->type = var->type; | |
3505 } | |
3506 | |
3507 int VarExp::equals(Object *o) | |
3508 { VarExp *ne; | |
3509 | |
3510 if (this == o || | |
3511 (((Expression *)o)->op == TOKvar && | |
3512 ((ne = (VarExp *)o), type->equals(ne->type)) && | |
3513 var == ne->var)) | |
3514 return 1; | |
3515 return 0; | |
3516 } | |
3517 | |
3518 Expression *VarExp::semantic(Scope *sc) | |
3519 { FuncLiteralDeclaration *fd; | |
3520 | |
3521 #if LOGSEMANTIC | |
3522 printf("VarExp::semantic(%s)\n", toChars()); | |
3523 #endif | |
3524 if (!type) | |
3525 { type = var->type; | |
3526 #if 0 | |
3527 if (var->storage_class & STClazy) | |
3528 { | |
3529 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd); | |
3530 type = new TypeDelegate(tf); | |
3531 type = type->semantic(loc, sc); | |
3532 } | |
3533 #endif | |
3534 } | |
3535 | |
163
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3536 // LLVMDC: Fixes bug 1161, http://d.puremagic.com/issues/show_bug.cgi?id=1161 |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3537 // check access to VarDeclaration |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3538 accessCheck(loc, sc, NULL, var); |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3539 |
159 | 3540 VarDeclaration *v = var->isVarDeclaration(); |
3541 if (v) | |
3542 { | |
3543 if (v->isConst() && type->toBasetype()->ty != Tsarray && v->init) | |
3544 { | |
3545 ExpInitializer *ei = v->init->isExpInitializer(); | |
3546 if (ei) | |
3547 { | |
3548 //ei->exp->implicitCastTo(sc, type)->print(); | |
3549 return ei->exp->implicitCastTo(sc, type); | |
3550 } | |
3551 } | |
3552 v->checkNestedReference(sc, loc); | |
3553 } | |
3554 #if 0 | |
3555 else if ((fd = var->isFuncLiteralDeclaration()) != NULL) | |
3556 { Expression *e; | |
3557 e = new FuncExp(loc, fd); | |
3558 e->type = type; | |
3559 return e; | |
3560 } | |
3561 #endif | |
3562 return this; | |
3563 } | |
3564 | |
3565 char *VarExp::toChars() | |
3566 { | |
3567 return var->toChars(); | |
3568 } | |
3569 | |
3570 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3571 { | |
3572 buf->writestring(var->toChars()); | |
3573 } | |
3574 | |
3575 void VarExp::checkEscape() | |
3576 { | |
3577 VarDeclaration *v = var->isVarDeclaration(); | |
3578 if (v) | |
3579 { Type *tb = v->type->toBasetype(); | |
3580 // if reference type | |
3581 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass) | |
3582 { | |
3583 if ((v->isAuto() || v->isScope()) && !v->noauto) | |
3584 error("escaping reference to auto local %s", v->toChars()); | |
3585 else if (v->storage_class & STCvariadic) | |
3586 error("escaping reference to variadic parameter %s", v->toChars()); | |
3587 } | |
3588 } | |
3589 } | |
3590 | |
3591 Expression *VarExp::toLvalue(Scope *sc, Expression *e) | |
3592 { | |
3593 #if 0 | |
3594 tym = tybasic(e1->ET->Tty); | |
3595 if (!(tyscalar(tym) || | |
3596 tym == TYstruct || | |
3597 tym == TYarray && e->Eoper == TOKaddr)) | |
3598 synerr(EM_lvalue); // lvalue expected | |
3599 #endif | |
3600 if (var->storage_class & STClazy) | |
3601 error("lazy variables cannot be lvalues"); | |
3602 return this; | |
3603 } | |
3604 | |
3605 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) | |
3606 { | |
3607 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); | |
3608 if (sc->incontract && var->isParameter()) | |
3609 error("cannot modify parameter '%s' in contract", var->toChars()); | |
3610 | |
3611 if (type && type->toBasetype()->ty == Tsarray) | |
3612 error("cannot change reference to static array '%s'", var->toChars()); | |
3613 | |
3614 VarDeclaration *v = var->isVarDeclaration(); | |
3615 if (v && v->canassign == 0 && | |
3616 (var->isConst() || (global.params.Dversion > 1 && var->isFinal()))) | |
3617 error("cannot modify final variable '%s'", var->toChars()); | |
3618 v->needsStorage = true; | |
3619 | |
3620 if (var->isCtorinit()) | |
3621 { // It's only modifiable if inside the right constructor | |
3622 Dsymbol *s = sc->func; | |
3623 while (1) | |
3624 { | |
3625 FuncDeclaration *fd = NULL; | |
3626 if (s) | |
3627 fd = s->isFuncDeclaration(); | |
3628 if (fd && | |
3629 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
3630 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
3631 fd->toParent() == var->toParent() | |
3632 ) | |
3633 { | |
3634 VarDeclaration *v = var->isVarDeclaration(); | |
3635 assert(v); | |
3636 v->ctorinit = 1; | |
3637 //printf("setting ctorinit\n"); | |
3638 } | |
3639 else | |
3640 { | |
3641 if (s) | |
3642 { s = s->toParent2(); | |
3643 continue; | |
3644 } | |
3645 else | |
3646 { | |
3647 const char *p = var->isStatic() ? "static " : ""; | |
3648 error("can only initialize %sconst %s inside %sconstructor", | |
3649 p, var->toChars(), p); | |
3650 } | |
3651 } | |
3652 break; | |
3653 } | |
3654 } | |
3655 | |
3656 // See if this expression is a modifiable lvalue (i.e. not const) | |
3657 return toLvalue(sc, e); | |
3658 } | |
3659 | |
3660 | |
3661 /******************************** TupleExp **************************/ | |
3662 | |
3663 TupleExp::TupleExp(Loc loc, Expressions *exps) | |
3664 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
3665 { | |
3666 //printf("TupleExp(this = %p)\n", this); | |
3667 this->exps = exps; | |
3668 this->type = NULL; | |
3669 } | |
3670 | |
3671 | |
3672 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) | |
3673 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
3674 { | |
3675 exps = new Expressions(); | |
3676 type = NULL; | |
3677 | |
3678 exps->reserve(tup->objects->dim); | |
3679 for (size_t i = 0; i < tup->objects->dim; i++) | |
3680 { Object *o = (Object *)tup->objects->data[i]; | |
3681 if (o->dyncast() == DYNCAST_EXPRESSION) | |
3682 { | |
3683 Expression *e = (Expression *)o; | |
3684 e = e->syntaxCopy(); | |
3685 exps->push(e); | |
3686 } | |
3687 else if (o->dyncast() == DYNCAST_DSYMBOL) | |
3688 { | |
3689 Dsymbol *s = (Dsymbol *)o; | |
3690 Expression *e = new DsymbolExp(loc, s); | |
3691 exps->push(e); | |
3692 } | |
3693 else if (o->dyncast() == DYNCAST_TYPE) | |
3694 { | |
3695 Type *t = (Type *)o; | |
3696 Expression *e = new TypeExp(loc, t); | |
3697 exps->push(e); | |
3698 } | |
3699 else | |
3700 { | |
3701 error("%s is not an expression", o->toChars()); | |
3702 } | |
3703 } | |
3704 } | |
3705 | |
3706 int TupleExp::equals(Object *o) | |
3707 { TupleExp *ne; | |
3708 | |
3709 if (this == o) | |
3710 return 1; | |
3711 if (((Expression *)o)->op == TOKtuple) | |
3712 { | |
3713 TupleExp *te = (TupleExp *)o; | |
3714 if (exps->dim != te->exps->dim) | |
3715 return 0; | |
3716 for (size_t i = 0; i < exps->dim; i++) | |
3717 { Expression *e1 = (Expression *)exps->data[i]; | |
3718 Expression *e2 = (Expression *)te->exps->data[i]; | |
3719 | |
3720 if (!e1->equals(e2)) | |
3721 return 0; | |
3722 } | |
3723 return 1; | |
3724 } | |
3725 return 0; | |
3726 } | |
3727 | |
3728 Expression *TupleExp::syntaxCopy() | |
3729 { | |
3730 return new TupleExp(loc, arraySyntaxCopy(exps)); | |
3731 } | |
3732 | |
3733 Expression *TupleExp::semantic(Scope *sc) | |
3734 { | |
3735 #if LOGSEMANTIC | |
3736 printf("+TupleExp::semantic(%s)\n", toChars()); | |
3737 #endif | |
3738 if (type) | |
3739 return this; | |
3740 | |
3741 // Run semantic() on each argument | |
3742 for (size_t i = 0; i < exps->dim; i++) | |
3743 { Expression *e = (Expression *)exps->data[i]; | |
3744 | |
3745 e = e->semantic(sc); | |
3746 if (!e->type) | |
3747 { error("%s has no value", e->toChars()); | |
3748 e->type = Type::terror; | |
3749 } | |
3750 exps->data[i] = (void *)e; | |
3751 } | |
3752 | |
3753 expandTuples(exps); | |
3754 if (0 && exps->dim == 1) | |
3755 { | |
3756 return (Expression *)exps->data[0]; | |
3757 } | |
3758 type = new TypeTuple(exps); | |
3759 //printf("-TupleExp::semantic(%s)\n", toChars()); | |
3760 return this; | |
3761 } | |
3762 | |
3763 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3764 { | |
3765 buf->writestring("tuple("); | |
3766 argsToCBuffer(buf, exps, hgs); | |
3767 buf->writeByte(')'); | |
3768 } | |
3769 | |
3770 int TupleExp::checkSideEffect(int flag) | |
3771 { int f = 0; | |
3772 | |
3773 for (int i = 0; i < exps->dim; i++) | |
3774 { Expression *e = (Expression *)exps->data[i]; | |
3775 | |
3776 f |= e->checkSideEffect(2); | |
3777 } | |
3778 if (flag == 0 && f == 0) | |
3779 Expression::checkSideEffect(0); | |
3780 return f; | |
3781 } | |
3782 | |
3783 void TupleExp::checkEscape() | |
3784 { | |
3785 for (size_t i = 0; i < exps->dim; i++) | |
3786 { Expression *e = (Expression *)exps->data[i]; | |
3787 e->checkEscape(); | |
3788 } | |
3789 } | |
3790 | |
3791 /******************************** FuncExp *********************************/ | |
3792 | |
3793 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd) | |
3794 : Expression(loc, TOKfunction, sizeof(FuncExp)) | |
3795 { | |
3796 this->fd = fd; | |
3797 } | |
3798 | |
3799 Expression *FuncExp::syntaxCopy() | |
3800 { | |
3801 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); | |
3802 } | |
3803 | |
3804 Expression *FuncExp::semantic(Scope *sc) | |
3805 { | |
3806 #if LOGSEMANTIC | |
3807 printf("FuncExp::semantic(%s)\n", toChars()); | |
3808 #endif | |
3809 if (!type) | |
3810 { | |
3811 fd->semantic(sc); | |
3812 fd->parent = sc->parent; | |
3813 if (global.errors) | |
3814 { | |
3815 if (!fd->type->next) | |
3816 fd->type->next = Type::terror; | |
3817 } | |
3818 else | |
3819 { | |
3820 fd->semantic2(sc); | |
3821 if (!global.errors) | |
3822 { | |
3823 fd->semantic3(sc); | |
3824 | |
3825 if (!global.errors && global.params.useInline) | |
3826 fd->inlineScan(); | |
3827 } | |
3828 } | |
3829 | |
3830 // Type is a "delegate to" or "pointer to" the function literal | |
3831 if (fd->isNested()) | |
3832 { | |
3833 type = new TypeDelegate(fd->type); | |
3834 type = type->semantic(loc, sc); | |
3835 } | |
3836 else | |
3837 { | |
3838 type = fd->type->pointerTo(); | |
3839 } | |
3840 } | |
3841 return this; | |
3842 } | |
3843 | |
3844 char *FuncExp::toChars() | |
3845 { | |
3846 return fd->toChars(); | |
3847 } | |
3848 | |
3849 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3850 { | |
3851 buf->writestring(fd->toChars()); | |
3852 } | |
3853 | |
3854 | |
3855 /******************************** DeclarationExp **************************/ | |
3856 | |
3857 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration) | |
3858 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp)) | |
3859 { | |
3860 this->declaration = declaration; | |
3861 } | |
3862 | |
3863 Expression *DeclarationExp::syntaxCopy() | |
3864 { | |
3865 return new DeclarationExp(loc, declaration->syntaxCopy(NULL)); | |
3866 } | |
3867 | |
3868 Expression *DeclarationExp::semantic(Scope *sc) | |
3869 { | |
3870 if (type) | |
3871 return this; | |
3872 | |
3873 #if LOGSEMANTIC | |
3874 printf("DeclarationExp::semantic() %s\n", toChars()); | |
3875 #endif | |
3876 | |
3877 /* This is here to support extern(linkage) declaration, | |
3878 * where the extern(linkage) winds up being an AttribDeclaration | |
3879 * wrapper. | |
3880 */ | |
3881 Dsymbol *s = declaration; | |
3882 | |
3883 AttribDeclaration *ad = declaration->isAttribDeclaration(); | |
3884 if (ad) | |
3885 { | |
3886 if (ad->decl && ad->decl->dim == 1) | |
3887 s = (Dsymbol *)ad->decl->data[0]; | |
3888 } | |
3889 | |
3890 if (s->isVarDeclaration()) | |
3891 { // Do semantic() on initializer first, so: | |
3892 // int a = a; | |
3893 // will be illegal. | |
3894 declaration->semantic(sc); | |
3895 s->parent = sc->parent; | |
3896 } | |
3897 | |
3898 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc); | |
3899 // Insert into both local scope and function scope. | |
3900 // Must be unique in both. | |
3901 if (s->ident) | |
3902 { | |
3903 if (!sc->insert(s)) | |
3904 error("declaration %s is already defined", s->toPrettyChars()); | |
3905 else if (sc->func) | |
3906 { VarDeclaration *v = s->isVarDeclaration(); | |
3907 if ((s->isFuncDeclaration() /*|| v && v->storage_class & STCstatic*/) && | |
3908 !sc->func->localsymtab->insert(s)) | |
3909 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars()); | |
3910 else if (!global.params.useDeprecated) | |
3911 { // Disallow shadowing | |
3912 | |
3913 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing) | |
3914 { Dsymbol *s2; | |
3915 | |
3916 if (scx->scopesym && scx->scopesym->symtab && | |
3917 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && | |
3918 s != s2) | |
3919 { | |
3920 error("shadowing declaration %s is deprecated", s->toPrettyChars()); | |
3921 } | |
3922 } | |
3923 } | |
3924 } | |
3925 } | |
3926 if (!s->isVarDeclaration()) | |
3927 { | |
3928 declaration->semantic(sc); | |
3929 s->parent = sc->parent; | |
3930 } | |
3931 if (!global.errors) | |
3932 { | |
3933 declaration->semantic2(sc); | |
3934 if (!global.errors) | |
3935 { | |
3936 declaration->semantic3(sc); | |
3937 | |
3938 if (!global.errors && global.params.useInline) | |
3939 declaration->inlineScan(); | |
3940 } | |
3941 } | |
3942 | |
3943 type = Type::tvoid; | |
3944 return this; | |
3945 } | |
3946 | |
3947 int DeclarationExp::checkSideEffect(int flag) | |
3948 { | |
3949 return 1; | |
3950 } | |
3951 | |
3952 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3953 { | |
3954 declaration->toCBuffer(buf, hgs); | |
3955 } | |
3956 | |
3957 | |
3958 /************************ TypeidExp ************************************/ | |
3959 | |
3960 /* | |
3961 * typeid(int) | |
3962 */ | |
3963 | |
3964 TypeidExp::TypeidExp(Loc loc, Type *typeidType) | |
3965 : Expression(loc, TOKtypeid, sizeof(TypeidExp)) | |
3966 { | |
3967 this->typeidType = typeidType; | |
3968 } | |
3969 | |
3970 | |
3971 Expression *TypeidExp::syntaxCopy() | |
3972 { | |
3973 return new TypeidExp(loc, typeidType->syntaxCopy()); | |
3974 } | |
3975 | |
3976 | |
3977 Expression *TypeidExp::semantic(Scope *sc) | |
3978 { Expression *e; | |
3979 | |
3980 #if LOGSEMANTIC | |
3981 printf("TypeidExp::semantic()\n"); | |
3982 #endif | |
3983 typeidType = typeidType->semantic(loc, sc); | |
3984 e = typeidType->getTypeInfo(sc); | |
3985 return e; | |
3986 } | |
3987 | |
3988 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3989 { | |
3990 buf->writestring("typeid("); | |
3991 typeidType->toCBuffer(buf, NULL, hgs); | |
3992 buf->writeByte(')'); | |
3993 } | |
3994 | |
3995 /************************************************************/ | |
3996 | |
3997 HaltExp::HaltExp(Loc loc) | |
3998 : Expression(loc, TOKhalt, sizeof(HaltExp)) | |
3999 { | |
4000 } | |
4001 | |
4002 Expression *HaltExp::semantic(Scope *sc) | |
4003 { | |
4004 #if LOGSEMANTIC | |
4005 printf("HaltExp::semantic()\n"); | |
4006 #endif | |
4007 type = Type::tvoid; | |
4008 return this; | |
4009 } | |
4010 | |
4011 int HaltExp::checkSideEffect(int flag) | |
4012 { | |
4013 return 1; | |
4014 } | |
4015 | |
4016 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4017 { | |
4018 buf->writestring("halt"); | |
4019 } | |
4020 | |
4021 /************************************************************/ | |
4022 | |
4023 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, | |
4024 Type *tspec, enum TOK tok2) | |
4025 : Expression(loc, TOKis, sizeof(IsExp)) | |
4026 { | |
4027 this->targ = targ; | |
4028 this->id = id; | |
4029 this->tok = tok; | |
4030 this->tspec = tspec; | |
4031 this->tok2 = tok2; | |
4032 } | |
4033 | |
4034 Expression *IsExp::syntaxCopy() | |
4035 { | |
4036 return new IsExp(loc, | |
4037 targ->syntaxCopy(), | |
4038 id, | |
4039 tok, | |
4040 tspec ? tspec->syntaxCopy() : NULL, | |
4041 tok2); | |
4042 } | |
4043 | |
4044 Expression *IsExp::semantic(Scope *sc) | |
4045 { Type *tded; | |
4046 | |
4047 //printf("IsExp::semantic()\n"); | |
4048 if (id && !(sc->flags & SCOPEstaticif)) | |
4049 error("can only declare type aliases within static if conditionals"); | |
4050 | |
4051 unsigned errors_save = global.errors; | |
4052 global.errors = 0; | |
4053 global.gag++; // suppress printing of error messages | |
4054 targ = targ->semantic(loc, sc); | |
4055 global.gag--; | |
4056 unsigned gerrors = global.errors; | |
4057 global.errors = errors_save; | |
4058 | |
4059 if (gerrors) // if any errors happened | |
4060 { // then condition is false | |
4061 goto Lno; | |
4062 } | |
4063 else if (tok2 != TOKreserved) | |
4064 { | |
4065 switch (tok2) | |
4066 { | |
4067 case TOKtypedef: | |
4068 if (targ->ty != Ttypedef) | |
4069 goto Lno; | |
4070 tded = ((TypeTypedef *)targ)->sym->basetype; | |
4071 break; | |
4072 | |
4073 case TOKstruct: | |
4074 if (targ->ty != Tstruct) | |
4075 goto Lno; | |
4076 if (((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4077 goto Lno; | |
4078 tded = targ; | |
4079 break; | |
4080 | |
4081 case TOKunion: | |
4082 if (targ->ty != Tstruct) | |
4083 goto Lno; | |
4084 if (!((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4085 goto Lno; | |
4086 tded = targ; | |
4087 break; | |
4088 | |
4089 case TOKclass: | |
4090 if (targ->ty != Tclass) | |
4091 goto Lno; | |
4092 if (((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4093 goto Lno; | |
4094 tded = targ; | |
4095 break; | |
4096 | |
4097 case TOKinterface: | |
4098 if (targ->ty != Tclass) | |
4099 goto Lno; | |
4100 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4101 goto Lno; | |
4102 tded = targ; | |
4103 break; | |
4104 | |
4105 case TOKsuper: | |
4106 // If class or interface, get the base class and interfaces | |
4107 if (targ->ty != Tclass) | |
4108 goto Lno; | |
4109 else | |
4110 { ClassDeclaration *cd = ((TypeClass *)targ)->sym; | |
4111 Arguments *args = new Arguments; | |
4112 args->reserve(cd->baseclasses.dim); | |
4113 for (size_t i = 0; i < cd->baseclasses.dim; i++) | |
4114 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; | |
4115 args->push(new Argument(STCin, b->type, NULL, NULL)); | |
4116 } | |
4117 tded = new TypeTuple(args); | |
4118 } | |
4119 break; | |
4120 | |
4121 case TOKenum: | |
4122 if (targ->ty != Tenum) | |
4123 goto Lno; | |
4124 tded = ((TypeEnum *)targ)->sym->memtype; | |
4125 break; | |
4126 | |
4127 case TOKdelegate: | |
4128 if (targ->ty != Tdelegate) | |
4129 goto Lno; | |
4130 tded = targ->next; // the underlying function type | |
4131 break; | |
4132 | |
4133 case TOKfunction: | |
4134 { if (targ->ty != Tfunction) | |
4135 goto Lno; | |
4136 tded = targ; | |
4137 | |
4138 /* Generate tuple from function parameter types. | |
4139 */ | |
4140 assert(tded->ty == Tfunction); | |
4141 Arguments *params = ((TypeFunction *)tded)->parameters; | |
4142 size_t dim = Argument::dim(params); | |
4143 Arguments *args = new Arguments; | |
4144 args->reserve(dim); | |
4145 for (size_t i = 0; i < dim; i++) | |
4146 { Argument *arg = Argument::getNth(params, i); | |
4147 assert(arg && arg->type); | |
4148 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL)); | |
4149 } | |
4150 tded = new TypeTuple(args); | |
4151 break; | |
4152 } | |
4153 case TOKreturn: | |
4154 /* Get the 'return type' for the function, | |
4155 * delegate, or pointer to function. | |
4156 */ | |
4157 if (targ->ty == Tfunction) | |
4158 tded = targ->next; | |
4159 else if (targ->ty == Tdelegate) | |
4160 tded = targ->next->next; | |
4161 else if (targ->ty == Tpointer && targ->next->ty == Tfunction) | |
4162 tded = targ->next->next; | |
4163 else | |
4164 goto Lno; | |
4165 break; | |
4166 | |
4167 default: | |
4168 assert(0); | |
4169 } | |
4170 goto Lyes; | |
4171 } | |
4172 else if (id && tspec) | |
4173 { | |
4174 /* Evaluate to TRUE if targ matches tspec. | |
4175 * If TRUE, declare id as an alias for the specialized type. | |
4176 */ | |
4177 | |
4178 MATCH m; | |
4179 TemplateTypeParameter tp(loc, id, NULL, NULL); | |
4180 | |
4181 TemplateParameters parameters; | |
4182 parameters.setDim(1); | |
4183 parameters.data[0] = (void *)&tp; | |
4184 | |
4185 Objects dedtypes; | |
4186 dedtypes.setDim(1); | |
4187 dedtypes.data[0] = NULL; | |
4188 | |
4189 m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes); | |
4190 if (m == MATCHnomatch || | |
4191 (m != MATCHexact && tok == TOKequal)) | |
4192 goto Lno; | |
4193 else | |
4194 { | |
4195 assert(dedtypes.dim == 1); | |
4196 tded = (Type *)dedtypes.data[0]; | |
4197 if (!tded) | |
4198 tded = targ; | |
4199 goto Lyes; | |
4200 } | |
4201 } | |
4202 else if (id) | |
4203 { | |
4204 /* Declare id as an alias for type targ. Evaluate to TRUE | |
4205 */ | |
4206 tded = targ; | |
4207 goto Lyes; | |
4208 } | |
4209 else if (tspec) | |
4210 { | |
4211 /* Evaluate to TRUE if targ matches tspec | |
4212 */ | |
4213 tspec = tspec->semantic(loc, sc); | |
4214 //printf("targ = %s\n", targ->toChars()); | |
4215 //printf("tspec = %s\n", tspec->toChars()); | |
4216 if (tok == TOKcolon) | |
4217 { if (targ->implicitConvTo(tspec)) | |
4218 goto Lyes; | |
4219 else | |
4220 goto Lno; | |
4221 } | |
4222 else /* == */ | |
4223 { if (targ->equals(tspec)) | |
4224 goto Lyes; | |
4225 else | |
4226 goto Lno; | |
4227 } | |
4228 } | |
4229 | |
4230 Lyes: | |
4231 if (id) | |
4232 { | |
4233 Dsymbol *s = new AliasDeclaration(loc, id, tded); | |
4234 s->semantic(sc); | |
4235 sc->insert(s); | |
4236 if (sc->sd) | |
4237 s->addMember(sc, sc->sd, 1); | |
4238 } | |
4239 return new IntegerExp(1); | |
4240 | |
4241 Lno: | |
4242 return new IntegerExp(0); | |
4243 } | |
4244 | |
4245 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4246 { | |
4247 buf->writestring("is("); | |
4248 targ->toCBuffer(buf, id, hgs); | |
4249 if (tok2 != TOKreserved) | |
4250 { | |
4251 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2)); | |
4252 } | |
4253 else if (tspec) | |
4254 { | |
4255 if (tok == TOKcolon) | |
4256 buf->writestring(" : "); | |
4257 else | |
4258 buf->writestring(" == "); | |
4259 tspec->toCBuffer(buf, NULL, hgs); | |
4260 } | |
4261 #if V2 | |
4262 if (parameters) | |
4263 { // First parameter is already output, so start with second | |
4264 for (int i = 1; i < parameters->dim; i++) | |
4265 { | |
4266 buf->writeByte(','); | |
4267 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
4268 tp->toCBuffer(buf, hgs); | |
4269 } | |
4270 } | |
4271 #endif | |
4272 buf->writeByte(')'); | |
4273 } | |
4274 | |
4275 | |
4276 /************************************************************/ | |
4277 | |
4278 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) | |
4279 : Expression(loc, op, size) | |
4280 { | |
4281 this->e1 = e1; | |
4282 } | |
4283 | |
4284 Expression *UnaExp::syntaxCopy() | |
4285 { UnaExp *e; | |
4286 | |
4287 e = (UnaExp *)copy(); | |
4288 e->type = NULL; | |
4289 e->e1 = e->e1->syntaxCopy(); | |
4290 return e; | |
4291 } | |
4292 | |
4293 Expression *UnaExp::semantic(Scope *sc) | |
4294 { | |
4295 #if LOGSEMANTIC | |
4296 printf("UnaExp::semantic('%s')\n", toChars()); | |
4297 #endif | |
4298 e1 = e1->semantic(sc); | |
4299 // if (!e1->type) | |
4300 // error("%s has no value", e1->toChars()); | |
4301 return this; | |
4302 } | |
4303 | |
4304 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4305 { | |
4306 buf->writestring(Token::toChars(op)); | |
4307 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4308 } | |
4309 | |
4310 /************************************************************/ | |
4311 | |
4312 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) | |
4313 : Expression(loc, op, size) | |
4314 { | |
4315 this->e1 = e1; | |
4316 this->e2 = e2; | |
4317 } | |
4318 | |
4319 Expression *BinExp::syntaxCopy() | |
4320 { BinExp *e; | |
4321 | |
4322 e = (BinExp *)copy(); | |
4323 e->type = NULL; | |
4324 e->e1 = e->e1->syntaxCopy(); | |
4325 e->e2 = e->e2->syntaxCopy(); | |
4326 return e; | |
4327 } | |
4328 | |
4329 Expression *BinExp::semantic(Scope *sc) | |
4330 { | |
4331 #if LOGSEMANTIC | |
4332 printf("BinExp::semantic('%s')\n", toChars()); | |
4333 #endif | |
4334 e1 = e1->semantic(sc); | |
4335 if (!e1->type) | |
4336 { | |
4337 error("%s has no value", e1->toChars()); | |
4338 e1->type = Type::terror; | |
4339 } | |
4340 e2 = e2->semantic(sc); | |
4341 if (!e2->type) | |
4342 { | |
4343 error("%s has no value", e2->toChars()); | |
4344 e2->type = Type::terror; | |
4345 } | |
4346 assert(e1->type); | |
4347 return this; | |
4348 } | |
4349 | |
4350 Expression *BinExp::semanticp(Scope *sc) | |
4351 { | |
4352 BinExp::semantic(sc); | |
4353 e1 = resolveProperties(sc, e1); | |
4354 e2 = resolveProperties(sc, e2); | |
4355 return this; | |
4356 } | |
4357 | |
4358 /*************************** | |
4359 * Common semantic routine for some xxxAssignExp's. | |
4360 */ | |
4361 | |
4362 Expression *BinExp::commonSemanticAssign(Scope *sc) | |
4363 { Expression *e; | |
4364 | |
4365 if (!type) | |
4366 { | |
4367 BinExp::semantic(sc); | |
4368 e2 = resolveProperties(sc, e2); | |
4369 | |
4370 e = op_overload(sc); | |
4371 if (e) | |
4372 return e; | |
4373 | |
4374 e1 = e1->modifiableLvalue(sc, e1); | |
4375 e1->checkScalar(); | |
4376 type = e1->type; | |
4377 if (type->toBasetype()->ty == Tbool) | |
4378 { | |
4379 error("operator not allowed on bool expression %s", toChars()); | |
4380 } | |
4381 typeCombine(sc); | |
4382 e1->checkArithmetic(); | |
4383 e2->checkArithmetic(); | |
4384 | |
4385 if (op == TOKmodass && e2->type->iscomplex()) | |
4386 { error("cannot perform modulo complex arithmetic"); | |
4387 return new IntegerExp(0); | |
4388 } | |
4389 } | |
4390 return this; | |
4391 } | |
4392 | |
4393 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc) | |
4394 { Expression *e; | |
4395 | |
4396 if (!type) | |
4397 { | |
4398 BinExp::semantic(sc); | |
4399 e2 = resolveProperties(sc, e2); | |
4400 | |
4401 e = op_overload(sc); | |
4402 if (e) | |
4403 return e; | |
4404 | |
4405 e1 = e1->modifiableLvalue(sc, e1); | |
4406 e1->checkScalar(); | |
4407 type = e1->type; | |
4408 if (type->toBasetype()->ty == Tbool) | |
4409 { | |
4410 e2 = e2->implicitCastTo(sc, type); | |
4411 } | |
4412 | |
4413 typeCombine(sc); | |
4414 e1->checkIntegral(); | |
4415 e2->checkIntegral(); | |
4416 } | |
4417 return this; | |
4418 } | |
4419 | |
4420 int BinExp::checkSideEffect(int flag) | |
4421 { | |
4422 if (op == TOKplusplus || | |
4423 op == TOKminusminus || | |
4424 op == TOKassign || | |
4425 op == TOKconstruct || | |
4426 op == TOKblit || | |
4427 op == TOKaddass || | |
4428 op == TOKminass || | |
4429 op == TOKcatass || | |
4430 op == TOKmulass || | |
4431 op == TOKdivass || | |
4432 op == TOKmodass || | |
4433 op == TOKshlass || | |
4434 op == TOKshrass || | |
4435 op == TOKushrass || | |
4436 op == TOKandass || | |
4437 op == TOKorass || | |
4438 op == TOKxorass || | |
4439 op == TOKin || | |
4440 op == TOKremove) | |
4441 return 1; | |
4442 return Expression::checkSideEffect(flag); | |
4443 } | |
4444 | |
4445 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4446 { | |
4447 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4448 buf->writeByte(' '); | |
4449 buf->writestring(Token::toChars(op)); | |
4450 buf->writeByte(' '); | |
4451 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1)); | |
4452 } | |
4453 | |
4454 int BinExp::isunsigned() | |
4455 { | |
4456 return e1->type->isunsigned() || e2->type->isunsigned(); | |
4457 } | |
4458 | |
4459 void BinExp::incompatibleTypes() | |
4460 { | |
4461 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", | |
4462 e1->toChars(), Token::toChars(op), e2->toChars(), | |
4463 e1->type->toChars(), e2->type->toChars()); | |
4464 } | |
4465 | |
4466 /************************************************************/ | |
4467 | |
4468 CompileExp::CompileExp(Loc loc, Expression *e) | |
4469 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e) | |
4470 { | |
4471 } | |
4472 | |
4473 Expression *CompileExp::semantic(Scope *sc) | |
4474 { | |
4475 #if LOGSEMANTIC | |
4476 printf("CompileExp::semantic('%s')\n", toChars()); | |
4477 #endif | |
4478 UnaExp::semantic(sc); | |
4479 e1 = resolveProperties(sc, e1); | |
4480 e1 = e1->optimize(WANTvalue | WANTinterpret); | |
4481 if (e1->op != TOKstring) | |
4482 { error("argument to mixin must be a string, not (%s)", e1->toChars()); | |
4483 type = Type::terror; | |
4484 return this; | |
4485 } | |
4486 StringExp *se = (StringExp *)e1; | |
4487 se = se->toUTF8(sc); | |
4488 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | |
4489 p.loc = loc; | |
4490 p.nextToken(); | |
4491 Expression *e = p.parseExpression(); | |
4492 if (p.token.value != TOKeof) | |
4493 error("incomplete mixin expression (%s)", se->toChars()); | |
4494 return e->semantic(sc); | |
4495 } | |
4496 | |
4497 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4498 { | |
4499 buf->writestring("mixin("); | |
4500 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4501 buf->writeByte(')'); | |
4502 } | |
4503 | |
4504 /************************************************************/ | |
4505 | |
4506 FileExp::FileExp(Loc loc, Expression *e) | |
4507 : UnaExp(loc, TOKmixin, sizeof(FileExp), e) | |
4508 { | |
4509 } | |
4510 | |
4511 Expression *FileExp::semantic(Scope *sc) | |
4512 { char *name; | |
4513 StringExp *se; | |
4514 | |
4515 #if LOGSEMANTIC | |
4516 printf("FileExp::semantic('%s')\n", toChars()); | |
4517 #endif | |
4518 UnaExp::semantic(sc); | |
4519 e1 = resolveProperties(sc, e1); | |
4520 e1 = e1->optimize(WANTvalue); | |
4521 if (e1->op != TOKstring) | |
4522 { error("file name argument must be a string, not (%s)", e1->toChars()); | |
4523 goto Lerror; | |
4524 } | |
4525 se = (StringExp *)e1; | |
4526 se = se->toUTF8(sc); | |
4527 name = (char *)se->string; | |
4528 | |
4529 if (!global.params.fileImppath) | |
4530 { error("need -Jpath switch to import text file %s", name); | |
4531 goto Lerror; | |
4532 } | |
4533 | |
4534 if (name != FileName::name(name)) | |
4535 { error("use -Jpath switch to provide path for filename %s", name); | |
4536 goto Lerror; | |
4537 } | |
4538 | |
4539 name = FileName::searchPath(global.filePath, name, 0); | |
4540 if (!name) | |
4541 { error("file %s cannot be found, check -Jpath", se->toChars()); | |
4542 goto Lerror; | |
4543 } | |
4544 | |
4545 if (global.params.verbose) | |
4546 printf("file %s\t(%s)\n", se->string, name); | |
4547 | |
4548 { File f(name); | |
4549 if (f.read()) | |
4550 { error("cannot read file %s", f.toChars()); | |
4551 goto Lerror; | |
4552 } | |
4553 else | |
4554 { | |
4555 f.ref = 1; | |
4556 se = new StringExp(loc, f.buffer, f.len); | |
4557 } | |
4558 } | |
4559 Lret: | |
4560 return se->semantic(sc); | |
4561 | |
4562 Lerror: | |
4563 se = new StringExp(loc, ""); | |
4564 goto Lret; | |
4565 } | |
4566 | |
4567 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4568 { | |
4569 buf->writestring("import("); | |
4570 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4571 buf->writeByte(')'); | |
4572 } | |
4573 | |
4574 /************************************************************/ | |
4575 | |
4576 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg) | |
4577 : UnaExp(loc, TOKassert, sizeof(AssertExp), e) | |
4578 { | |
4579 this->msg = msg; | |
4580 } | |
4581 | |
4582 Expression *AssertExp::syntaxCopy() | |
4583 { | |
4584 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(), | |
4585 msg ? msg->syntaxCopy() : NULL); | |
4586 return ae; | |
4587 } | |
4588 | |
4589 Expression *AssertExp::semantic(Scope *sc) | |
4590 { | |
4591 #if LOGSEMANTIC | |
4592 printf("AssertExp::semantic('%s')\n", toChars()); | |
4593 #endif | |
4594 UnaExp::semantic(sc); | |
4595 e1 = resolveProperties(sc, e1); | |
4596 // BUG: see if we can do compile time elimination of the Assert | |
4597 e1 = e1->optimize(WANTvalue); | |
4598 e1 = e1->checkToBoolean(); | |
4599 if (msg) | |
4600 { | |
4601 msg = msg->semantic(sc); | |
4602 msg = resolveProperties(sc, msg); | |
4603 msg = msg->implicitCastTo(sc, Type::tchar->arrayOf()); | |
4604 msg = msg->optimize(WANTvalue); | |
4605 } | |
4606 if (e1->isBool(FALSE)) | |
4607 { | |
4608 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
4609 fd->hasReturnExp |= 4; | |
4610 | |
4611 if (!global.params.useAssert) | |
4612 { Expression *e = new HaltExp(loc); | |
4613 e = e->semantic(sc); | |
4614 return e; | |
4615 } | |
4616 } | |
4617 type = Type::tvoid; | |
4618 return this; | |
4619 } | |
4620 | |
4621 int AssertExp::checkSideEffect(int flag) | |
4622 { | |
4623 return 1; | |
4624 } | |
4625 | |
4626 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4627 { | |
4628 buf->writestring("assert("); | |
4629 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4630 if (msg) | |
4631 { | |
4632 buf->writeByte(','); | |
4633 expToCBuffer(buf, hgs, msg, PREC_assign); | |
4634 } | |
4635 buf->writeByte(')'); | |
4636 } | |
4637 | |
4638 /************************************************************/ | |
4639 | |
4640 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) | |
4641 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e) | |
4642 { | |
4643 this->ident = ident; | |
4644 } | |
4645 | |
4646 Expression *DotIdExp::semantic(Scope *sc) | |
4647 { Expression *e; | |
4648 Expression *eleft; | |
4649 Expression *eright; | |
4650 | |
4651 #if LOGSEMANTIC | |
4652 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars()); | |
4653 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
4654 #endif | |
4655 | |
4656 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } | |
4657 | |
4658 #if 0 | |
4659 /* Don't do semantic analysis if we'll be converting | |
4660 * it to a string. | |
4661 */ | |
4662 if (ident == Id::stringof) | |
4663 { char *s = e1->toChars(); | |
4664 e = new StringExp(loc, s, strlen(s), 'c'); | |
4665 e = e->semantic(sc); | |
4666 return e; | |
4667 } | |
4668 #endif | |
4669 | |
4670 /* Special case: rewrite this.id and super.id | |
4671 * to be classtype.id and baseclasstype.id | |
4672 * if we have no this pointer. | |
4673 */ | |
4674 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) | |
4675 { ClassDeclaration *cd; | |
4676 StructDeclaration *sd; | |
4677 AggregateDeclaration *ad; | |
4678 | |
4679 ad = sc->getStructClassScope(); | |
4680 if (ad) | |
4681 { | |
4682 cd = ad->isClassDeclaration(); | |
4683 if (cd) | |
4684 { | |
4685 if (e1->op == TOKthis) | |
4686 { | |
4687 e = new TypeDotIdExp(loc, cd->type, ident); | |
4688 return e->semantic(sc); | |
4689 } | |
4690 else if (cd->baseClass && e1->op == TOKsuper) | |
4691 { | |
4692 e = new TypeDotIdExp(loc, cd->baseClass->type, ident); | |
4693 return e->semantic(sc); | |
4694 } | |
4695 } | |
4696 else | |
4697 { | |
4698 sd = ad->isStructDeclaration(); | |
4699 if (sd) | |
4700 { | |
4701 if (e1->op == TOKthis) | |
4702 { | |
4703 e = new TypeDotIdExp(loc, sd->type, ident); | |
4704 return e->semantic(sc); | |
4705 } | |
4706 } | |
4707 } | |
4708 } | |
4709 } | |
4710 | |
4711 UnaExp::semantic(sc); | |
4712 | |
4713 if (e1->op == TOKdotexp) | |
4714 { | |
4715 DotExp *de = (DotExp *)e1; | |
4716 eleft = de->e1; | |
4717 eright = de->e2; | |
4718 } | |
4719 else | |
4720 { | |
4721 e1 = resolveProperties(sc, e1); | |
4722 eleft = NULL; | |
4723 eright = e1; | |
4724 } | |
4725 | |
4726 if (e1->op == TOKtuple && ident == Id::length) | |
4727 { | |
4728 TupleExp *te = (TupleExp *)e1; | |
4729 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); | |
4730 return e; | |
4731 } | |
4732 | |
4733 if (eright->op == TOKimport) // also used for template alias's | |
4734 { | |
4735 Dsymbol *s; | |
4736 ScopeExp *ie = (ScopeExp *)eright; | |
4737 | |
4738 s = ie->sds->search(loc, ident, 0); | |
4739 if (s) | |
4740 { | |
4741 s = s->toAlias(); | |
4742 checkDeprecated(sc, s); | |
4743 | |
4744 EnumMember *em = s->isEnumMember(); | |
4745 if (em) | |
4746 { | |
4747 e = em->value; | |
4748 e = e->semantic(sc); | |
4749 return e; | |
4750 } | |
4751 | |
4752 VarDeclaration *v = s->isVarDeclaration(); | |
4753 if (v) | |
4754 { | |
4755 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
4756 if (v->inuse) | |
4757 { | |
4758 error("circular reference to '%s'", v->toChars()); | |
4759 type = Type::tint32; | |
4760 return this; | |
4761 } | |
4762 type = v->type; | |
4763 if (v->isConst()) | |
4764 { | |
4765 if (v->init) | |
4766 { | |
4767 ExpInitializer *ei = v->init->isExpInitializer(); | |
4768 if (ei) | |
4769 { | |
4770 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars()); | |
4771 //ei->exp = ei->exp->semantic(sc); | |
4772 if (ei->exp->type == type) | |
4773 { | |
4774 e = ei->exp->copy(); // make copy so we can change loc | |
4775 e->loc = loc; | |
4776 return e; | |
4777 } | |
4778 } | |
4779 } | |
4780 else if (type->isscalar()) | |
4781 { | |
4782 e = type->defaultInit(); | |
4783 e->loc = loc; | |
4784 return e; | |
4785 } | |
4786 } | |
4787 if (v->needThis()) | |
4788 { | |
4789 if (!eleft) | |
4790 eleft = new ThisExp(loc); | |
4791 e = new DotVarExp(loc, eleft, v); | |
4792 e = e->semantic(sc); | |
4793 } | |
4794 else | |
4795 { | |
4796 e = new VarExp(loc, v); | |
4797 if (eleft) | |
4798 { e = new CommaExp(loc, eleft, e); | |
4799 e->type = v->type; | |
4800 } | |
4801 } | |
4802 return e->deref(); | |
4803 } | |
4804 | |
4805 FuncDeclaration *f = s->isFuncDeclaration(); | |
4806 if (f) | |
4807 { | |
4808 //printf("it's a function\n"); | |
4809 if (f->needThis()) | |
4810 { | |
4811 if (!eleft) | |
4812 eleft = new ThisExp(loc); | |
4813 e = new DotVarExp(loc, eleft, f); | |
4814 e = e->semantic(sc); | |
4815 } | |
4816 else | |
4817 { | |
4818 e = new VarExp(loc, f); | |
4819 if (eleft) | |
4820 { e = new CommaExp(loc, eleft, e); | |
4821 e->type = f->type; | |
4822 } | |
4823 } | |
4824 return e; | |
4825 } | |
4826 | |
4827 Type *t = s->getType(); | |
4828 if (t) | |
4829 { | |
4830 return new TypeExp(loc, t); | |
4831 } | |
4832 | |
4833 ScopeDsymbol *sds = s->isScopeDsymbol(); | |
4834 if (sds) | |
4835 { | |
4836 //printf("it's a ScopeDsymbol\n"); | |
4837 e = new ScopeExp(loc, sds); | |
4838 e = e->semantic(sc); | |
4839 if (eleft) | |
4840 e = new DotExp(loc, eleft, e); | |
4841 return e; | |
4842 } | |
4843 | |
4844 Import *imp = s->isImport(); | |
4845 if (imp) | |
4846 { | |
4847 ScopeExp *ie; | |
4848 | |
4849 ie = new ScopeExp(loc, imp->pkg); | |
4850 return ie->semantic(sc); | |
4851 } | |
4852 | |
4853 // BUG: handle other cases like in IdentifierExp::semantic() | |
4854 #ifdef DEBUG | |
4855 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind()); | |
4856 #endif | |
4857 assert(0); | |
4858 } | |
4859 else if (ident == Id::stringof) | |
4860 { char *s = ie->toChars(); | |
4861 e = new StringExp(loc, s, strlen(s), 'c'); | |
4862 e = e->semantic(sc); | |
4863 return e; | |
4864 } | |
4865 error("undefined identifier %s", toChars()); | |
4866 type = Type::tvoid; | |
4867 return this; | |
4868 } | |
4869 else if (e1->type->ty == Tpointer && | |
4870 ident != Id::init && ident != Id::__sizeof && | |
4871 ident != Id::alignof && ident != Id::offsetof && | |
4872 ident != Id::mangleof && ident != Id::stringof) | |
4873 { | |
4874 e = new PtrExp(loc, e1); | |
4875 e->type = e1->type->next; | |
4876 return e->type->dotExp(sc, e, ident); | |
4877 } | |
4878 else | |
4879 { | |
4880 e = e1->type->dotExp(sc, e1, ident); | |
4881 e = e->semantic(sc); | |
4882 return e; | |
4883 } | |
4884 } | |
4885 | |
4886 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4887 { | |
4888 //printf("DotIdExp::toCBuffer()\n"); | |
4889 expToCBuffer(buf, hgs, e1, PREC_primary); | |
4890 buf->writeByte('.'); | |
4891 buf->writestring(ident->toChars()); | |
4892 } | |
4893 | |
4894 /********************** DotTemplateExp ***********************************/ | |
4895 | |
4896 // Mainly just a placeholder | |
4897 | |
4898 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td) | |
4899 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e) | |
4900 | |
4901 { | |
4902 this->td = td; | |
4903 } | |
4904 | |
4905 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4906 { | |
4907 expToCBuffer(buf, hgs, e1, PREC_primary); | |
4908 buf->writeByte('.'); | |
4909 buf->writestring(td->toChars()); | |
4910 } | |
4911 | |
4912 | |
4913 /************************************************************/ | |
4914 | |
4915 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v) | |
4916 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e) | |
4917 { | |
4918 //printf("DotVarExp()\n"); | |
4919 this->var = v; | |
4920 } | |
4921 | |
4922 Expression *DotVarExp::semantic(Scope *sc) | |
4923 { | |
4924 #if LOGSEMANTIC | |
4925 printf("DotVarExp::semantic('%s')\n", toChars()); | |
4926 #endif | |
4927 if (!type) | |
4928 { | |
4929 var = var->toAlias()->isDeclaration(); | |
4930 | |
4931 TupleDeclaration *tup = var->isTupleDeclaration(); | |
4932 if (tup) | |
4933 { /* Replace: | |
4934 * e1.tuple(a, b, c) | |
4935 * with: | |
4936 * tuple(e1.a, e1.b, e1.c) | |
4937 */ | |
4938 Expressions *exps = new Expressions; | |
4939 | |
4940 exps->reserve(tup->objects->dim); | |
4941 for (size_t i = 0; i < tup->objects->dim; i++) | |
4942 { Object *o = (Object *)tup->objects->data[i]; | |
4943 if (o->dyncast() != DYNCAST_EXPRESSION) | |
4944 { | |
4945 error("%s is not an expression", o->toChars()); | |
4946 } | |
4947 else | |
4948 { | |
4949 Expression *e = (Expression *)o; | |
4950 if (e->op != TOKdsymbol) | |
4951 error("%s is not a member", e->toChars()); | |
4952 else | |
4953 { DsymbolExp *ve = (DsymbolExp *)e; | |
4954 | |
4955 e = new DotVarExp(loc, e1, ve->s->isDeclaration()); | |
4956 exps->push(e); | |
4957 } | |
4958 } | |
4959 } | |
4960 Expression *e = new TupleExp(loc, exps); | |
4961 e = e->semantic(sc); | |
4962 return e; | |
4963 } | |
4964 | |
4965 e1 = e1->semantic(sc); | |
4966 type = var->type; | |
4967 if (!type && global.errors) | |
4968 { // var is goofed up, just return 0 | |
4969 return new IntegerExp(0); | |
4970 } | |
4971 assert(type); | |
4972 | |
4973 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution | |
4974 { | |
4975 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration(); | |
4976 L1: | |
4977 Type *t = e1->type->toBasetype(); | |
4978 | |
4979 if (ad && | |
4980 !(t->ty == Tpointer && t->next->ty == Tstruct && | |
4981 ((TypeStruct *)t->next)->sym == ad) | |
4982 && | |
4983 !(t->ty == Tstruct && | |
4984 ((TypeStruct *)t)->sym == ad) | |
4985 ) | |
4986 { | |
4987 ClassDeclaration *cd = ad->isClassDeclaration(); | |
4988 ClassDeclaration *tcd = t->isClassHandle(); | |
4989 | |
4990 if (!cd || !tcd || | |
4991 !(tcd == cd || cd->isBaseOf(tcd, NULL)) | |
4992 ) | |
4993 { | |
4994 if (tcd && tcd->isNested()) | |
4995 { // Try again with outer scope | |
4996 | |
4997 e1 = new DotVarExp(loc, e1, tcd->vthis); | |
4998 e1 = e1->semantic(sc); | |
4999 | |
5000 // Skip over nested functions, and get the enclosing | |
5001 // class type. | |
5002 Dsymbol *s = tcd->toParent(); | |
5003 while (s && s->isFuncDeclaration()) | |
5004 { FuncDeclaration *f = s->isFuncDeclaration(); | |
5005 if (f->vthis) | |
5006 { | |
5007 e1 = new VarExp(loc, f->vthis); | |
5008 } | |
5009 s = s->toParent(); | |
5010 } | |
5011 if (s && s->isClassDeclaration()) | |
5012 e1->type = s->isClassDeclaration()->type; | |
5013 | |
5014 e1 = e1->semantic(sc); | |
5015 goto L1; | |
5016 } | |
5017 #ifdef DEBUG | |
5018 printf("2: "); | |
5019 #endif | |
5020 error("this for %s needs to be type %s not type %s", | |
5021 var->toChars(), ad->toChars(), t->toChars()); | |
5022 } | |
5023 } | |
5024 accessCheck(loc, sc, e1, var); | |
5025 } | |
5026 } | |
5027 //printf("-DotVarExp::semantic('%s')\n", toChars()); | |
5028 return this; | |
5029 } | |
5030 | |
5031 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e) | |
5032 { | |
5033 //printf("DotVarExp::toLvalue(%s)\n", toChars()); | |
5034 return this; | |
5035 } | |
5036 | |
5037 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) | |
5038 { | |
5039 //printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); | |
5040 | |
5041 if (var->isCtorinit()) | |
5042 { // It's only modifiable if inside the right constructor | |
5043 Dsymbol *s = sc->func; | |
5044 while (1) | |
5045 { | |
5046 FuncDeclaration *fd = NULL; | |
5047 if (s) | |
5048 fd = s->isFuncDeclaration(); | |
5049 if (fd && | |
5050 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
5051 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
5052 fd->toParent() == var->toParent() && | |
5053 e1->op == TOKthis | |
5054 ) | |
5055 { | |
5056 VarDeclaration *v = var->isVarDeclaration(); | |
5057 assert(v); | |
5058 v->ctorinit = 1; | |
5059 //printf("setting ctorinit\n"); | |
5060 } | |
5061 else | |
5062 { | |
5063 if (s) | |
5064 { s = s->toParent2(); | |
5065 continue; | |
5066 } | |
5067 else | |
5068 { | |
5069 const char *p = var->isStatic() ? "static " : ""; | |
5070 error("can only initialize %sconst member %s inside %sconstructor", | |
5071 p, var->toChars(), p); | |
5072 } | |
5073 } | |
5074 break; | |
5075 } | |
5076 } | |
5077 return this; | |
5078 } | |
5079 | |
5080 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5081 { | |
5082 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5083 buf->writeByte('.'); | |
5084 buf->writestring(var->toChars()); | |
5085 } | |
5086 | |
5087 /************************************************************/ | |
5088 | |
5089 /* Things like: | |
5090 * foo.bar!(args) | |
5091 */ | |
5092 | |
5093 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti) | |
5094 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) | |
5095 { | |
5096 //printf("DotTemplateInstanceExp()\n"); | |
5097 this->ti = ti; | |
5098 } | |
5099 | |
5100 Expression *DotTemplateInstanceExp::syntaxCopy() | |
5101 { | |
5102 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc, | |
5103 e1->syntaxCopy(), | |
5104 (TemplateInstance *)ti->syntaxCopy(NULL)); | |
5105 return de; | |
5106 } | |
5107 | |
5108 Expression *DotTemplateInstanceExp::semantic(Scope *sc) | |
5109 { Dsymbol *s; | |
5110 Dsymbol *s2; | |
5111 TemplateDeclaration *td; | |
5112 Expression *e; | |
5113 Identifier *id; | |
5114 Type *t1; | |
5115 Expression *eleft = NULL; | |
5116 Expression *eright; | |
5117 | |
5118 #if LOGSEMANTIC | |
5119 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); | |
5120 #endif | |
5121 //e1->print(); | |
5122 //print(); | |
5123 e1 = e1->semantic(sc); | |
5124 t1 = e1->type; | |
5125 if (t1) | |
5126 t1 = t1->toBasetype(); | |
5127 //t1->print(); | |
5128 if (e1->op == TOKdotexp) | |
5129 { DotExp *de = (DotExp *)e1; | |
5130 eleft = de->e1; | |
5131 eright = de->e2; | |
5132 } | |
5133 else | |
5134 { eleft = NULL; | |
5135 eright = e1; | |
5136 } | |
5137 if (eright->op == TOKimport) | |
5138 { | |
5139 s = ((ScopeExp *)eright)->sds; | |
5140 } | |
5141 else if (e1->op == TOKtype) | |
5142 { | |
5143 s = t1->isClassHandle(); | |
5144 if (!s) | |
5145 { if (t1->ty == Tstruct) | |
5146 s = ((TypeStruct *)t1)->sym; | |
5147 else | |
5148 goto L1; | |
5149 } | |
5150 } | |
5151 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass)) | |
5152 { | |
5153 s = t1->toDsymbol(sc); | |
5154 eleft = e1; | |
5155 } | |
5156 else if (t1 && t1->ty == Tpointer) | |
5157 { | |
5158 t1 = t1->next->toBasetype(); | |
5159 if (t1->ty != Tstruct) | |
5160 goto L1; | |
5161 s = t1->toDsymbol(sc); | |
5162 eleft = e1; | |
5163 } | |
5164 else | |
5165 { | |
5166 L1: | |
5167 error("template %s is not a member of %s", ti->toChars(), e1->toChars()); | |
5168 goto Lerr; | |
5169 } | |
5170 | |
5171 assert(s); | |
5172 id = ti->name; | |
5173 s2 = s->search(loc, id, 0); | |
5174 if (!s2) | |
5175 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars()); | |
5176 goto Lerr; | |
5177 } | |
5178 s = s2; | |
5179 s->semantic(sc); | |
5180 s = s->toAlias(); | |
5181 td = s->isTemplateDeclaration(); | |
5182 if (!td) | |
5183 { | |
5184 error("%s is not a template", id->toChars()); | |
5185 goto Lerr; | |
5186 } | |
5187 if (global.errors) | |
5188 goto Lerr; | |
5189 | |
5190 ti->tempdecl = td; | |
5191 | |
5192 if (eleft) | |
5193 { Declaration *v; | |
5194 | |
5195 ti->semantic(sc); | |
5196 s = ti->inst->toAlias(); | |
5197 v = s->isDeclaration(); | |
5198 if (v) | |
5199 { e = new DotVarExp(loc, eleft, v); | |
5200 e = e->semantic(sc); | |
5201 return e; | |
5202 } | |
5203 } | |
5204 | |
5205 e = new ScopeExp(loc, ti); | |
5206 if (eleft) | |
5207 { | |
5208 e = new DotExp(loc, eleft, e); | |
5209 } | |
5210 e = e->semantic(sc); | |
5211 return e; | |
5212 | |
5213 Lerr: | |
5214 return new IntegerExp(0); | |
5215 } | |
5216 | |
5217 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5218 { | |
5219 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5220 buf->writeByte('.'); | |
5221 ti->toCBuffer(buf, hgs); | |
5222 } | |
5223 | |
5224 /************************************************************/ | |
5225 | |
5226 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f) | |
5227 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) | |
5228 { | |
5229 this->func = f; | |
5230 } | |
5231 | |
5232 Expression *DelegateExp::semantic(Scope *sc) | |
5233 { | |
5234 #if LOGSEMANTIC | |
5235 printf("DelegateExp::semantic('%s')\n", toChars()); | |
5236 #endif | |
5237 if (!type) | |
5238 { | |
5239 e1 = e1->semantic(sc); | |
5240 type = new TypeDelegate(func->type); | |
5241 type = type->semantic(loc, sc); | |
5242 //----------------- | |
5243 /* For func, we need to get the | |
5244 * right 'this' pointer if func is in an outer class, but our | |
5245 * existing 'this' pointer is in an inner class. | |
5246 * This code is analogous to that used for variables | |
5247 * in DotVarExp::semantic(). | |
5248 */ | |
5249 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); | |
5250 L10: | |
5251 Type *t = e1->type; | |
5252 if (func->needThis() && ad && | |
5253 !(t->ty == Tpointer && t->next->ty == Tstruct && | |
5254 ((TypeStruct *)t->next)->sym == ad) && | |
5255 !(t->ty == Tstruct && ((TypeStruct *)t)->sym == ad) | |
5256 ) | |
5257 { | |
5258 ClassDeclaration *cd = ad->isClassDeclaration(); | |
5259 ClassDeclaration *tcd = t->isClassHandle(); | |
5260 | |
5261 if (!cd || !tcd || | |
5262 !(tcd == cd || cd->isBaseOf(tcd, NULL)) | |
5263 ) | |
5264 { | |
5265 if (tcd && tcd->isNested()) | |
5266 { // Try again with outer scope | |
5267 | |
5268 e1 = new DotVarExp(loc, e1, tcd->vthis); | |
5269 e1 = e1->semantic(sc); | |
5270 goto L10; | |
5271 } | |
5272 #ifdef DEBUG | |
5273 printf("3: "); | |
5274 #endif | |
5275 error("this for %s needs to be type %s not type %s", | |
5276 func->toChars(), ad->toChars(), t->toChars()); | |
5277 } | |
5278 } | |
5279 //----------------- | |
5280 } | |
5281 return this; | |
5282 } | |
5283 | |
5284 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5285 { | |
5286 buf->writeByte('&'); | |
5287 if (!func->isNested()) | |
5288 { | |
5289 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5290 buf->writeByte('.'); | |
5291 } | |
5292 buf->writestring(func->toChars()); | |
5293 } | |
5294 | |
5295 /************************************************************/ | |
5296 | |
5297 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s) | |
5298 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e) | |
5299 { | |
5300 this->sym = s; | |
5301 this->type = s->getType(); | |
5302 } | |
5303 | |
5304 Expression *DotTypeExp::semantic(Scope *sc) | |
5305 { | |
5306 #if LOGSEMANTIC | |
5307 printf("DotTypeExp::semantic('%s')\n", toChars()); | |
5308 #endif | |
5309 UnaExp::semantic(sc); | |
5310 return this; | |
5311 } | |
5312 | |
5313 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5314 { | |
5315 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5316 buf->writeByte('.'); | |
5317 buf->writestring(sym->toChars()); | |
5318 } | |
5319 | |
5320 /************************************************************/ | |
5321 | |
5322 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps) | |
5323 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5324 { | |
5325 this->arguments = exps; | |
5326 } | |
5327 | |
5328 CallExp::CallExp(Loc loc, Expression *e) | |
5329 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5330 { | |
5331 this->arguments = NULL; | |
5332 } | |
5333 | |
5334 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) | |
5335 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5336 { | |
5337 Expressions *arguments = new Expressions(); | |
5338 arguments->setDim(1); | |
5339 arguments->data[0] = (void *)earg1; | |
5340 | |
5341 this->arguments = arguments; | |
5342 } | |
5343 | |
5344 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) | |
5345 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5346 { | |
5347 Expressions *arguments = new Expressions(); | |
5348 arguments->setDim(2); | |
5349 arguments->data[0] = (void *)earg1; | |
5350 arguments->data[1] = (void *)earg2; | |
5351 | |
5352 this->arguments = arguments; | |
5353 } | |
5354 | |
5355 Expression *CallExp::syntaxCopy() | |
5356 { | |
5357 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
5358 } | |
5359 | |
5360 | |
5361 Expression *CallExp::semantic(Scope *sc) | |
5362 { | |
5363 TypeFunction *tf; | |
5364 FuncDeclaration *f; | |
5365 int i; | |
5366 Type *t1; | |
5367 int istemp; | |
5368 | |
5369 #if LOGSEMANTIC | |
5370 printf("CallExp::semantic() %s\n", toChars()); | |
5371 #endif | |
5372 if (type) | |
5373 return this; // semantic() already run | |
5374 #if 0 | |
5375 if (arguments && arguments->dim) | |
5376 { | |
5377 Expression *earg = (Expression *)arguments->data[0]; | |
5378 earg->print(); | |
5379 if (earg->type) earg->type->print(); | |
5380 } | |
5381 #endif | |
5382 | |
5383 if (e1->op == TOKdelegate) | |
5384 { DelegateExp *de = (DelegateExp *)e1; | |
5385 | |
5386 e1 = new DotVarExp(de->loc, de->e1, de->func); | |
5387 return semantic(sc); | |
5388 } | |
5389 | |
5390 /* Transform: | |
5391 * array.id(args) into id(array,args) | |
5392 * aa.remove(arg) into delete aa[arg] | |
5393 */ | |
5394 if (e1->op == TOKdot) | |
5395 { | |
5396 // BUG: we should handle array.a.b.c.e(args) too | |
5397 | |
5398 DotIdExp *dotid = (DotIdExp *)(e1); | |
5399 dotid->e1 = dotid->e1->semantic(sc); | |
5400 assert(dotid->e1); | |
5401 if (dotid->e1->type) | |
5402 { | |
5403 TY e1ty = dotid->e1->type->toBasetype()->ty; | |
5404 if (e1ty == Taarray && dotid->ident == Id::remove) | |
5405 { | |
5406 if (!arguments || arguments->dim != 1) | |
5407 { error("expected key as argument to aa.remove()"); | |
5408 goto Lagain; | |
5409 } | |
5410 Expression *key = (Expression *)arguments->data[0]; | |
5411 key = key->semantic(sc); | |
5412 key = resolveProperties(sc, key); | |
5413 key->rvalue(); | |
5414 | |
5415 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype(); | |
5416 key = key->implicitCastTo(sc, taa->index); | |
5417 key = key->implicitCastTo(sc, taa->key); | |
5418 | |
5419 return new RemoveExp(loc, dotid->e1, key); | |
5420 } | |
5421 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray) | |
5422 { | |
5423 if (!arguments) | |
5424 arguments = new Expressions(); | |
5425 arguments->shift(dotid->e1); | |
5426 e1 = new IdentifierExp(dotid->loc, dotid->ident); | |
5427 } | |
5428 } | |
5429 } | |
5430 | |
5431 istemp = 0; | |
5432 Lagain: | |
5433 f = NULL; | |
5434 if (e1->op == TOKthis || e1->op == TOKsuper) | |
5435 { | |
5436 // semantic() run later for these | |
5437 } | |
5438 else | |
5439 { | |
5440 UnaExp::semantic(sc); | |
5441 | |
5442 /* Look for e1 being a lazy parameter | |
5443 */ | |
5444 if (e1->op == TOKvar) | |
5445 { VarExp *ve = (VarExp *)e1; | |
5446 | |
5447 if (ve->var->storage_class & STClazy) | |
5448 { | |
5449 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd); | |
5450 TypeDelegate *t = new TypeDelegate(tf); | |
5451 ve->type = t->semantic(loc, sc); | |
5452 } | |
5453 } | |
5454 | |
5455 if (e1->op == TOKimport) | |
5456 { // Perhaps this should be moved to ScopeExp::semantic() | |
5457 ScopeExp *se = (ScopeExp *)e1; | |
5458 e1 = new DsymbolExp(loc, se->sds); | |
5459 e1 = e1->semantic(sc); | |
5460 } | |
5461 #if 1 // patch for #540 by Oskar Linde | |
5462 else if (e1->op == TOKdotexp) | |
5463 { | |
5464 DotExp *de = (DotExp *) e1; | |
5465 | |
5466 if (de->e2->op == TOKimport) | |
5467 { // This should *really* be moved to ScopeExp::semantic() | |
5468 ScopeExp *se = (ScopeExp *)de->e2; | |
5469 de->e2 = new DsymbolExp(loc, se->sds); | |
5470 de->e2 = de->e2->semantic(sc); | |
5471 } | |
5472 | |
5473 if (de->e2->op == TOKtemplate) | |
5474 { TemplateExp *te = (TemplateExp *) de->e2; | |
5475 e1 = new DotTemplateExp(loc,de->e1,te->td); | |
5476 } | |
5477 } | |
5478 #endif | |
5479 } | |
5480 | |
5481 if (e1->op == TOKcomma) | |
5482 { | |
5483 CommaExp *ce = (CommaExp *)e1; | |
5484 | |
5485 e1 = ce->e2; | |
5486 e1->type = ce->type; | |
5487 ce->e2 = this; | |
5488 ce->type = NULL; | |
5489 return ce->semantic(sc); | |
5490 } | |
5491 | |
5492 t1 = NULL; | |
5493 if (e1->type) | |
5494 t1 = e1->type->toBasetype(); | |
5495 | |
5496 // Check for call operator overload | |
5497 if (t1) | |
5498 { AggregateDeclaration *ad; | |
5499 | |
5500 if (t1->ty == Tstruct) | |
5501 { | |
5502 ad = ((TypeStruct *)t1)->sym; | |
5503 if (search_function(ad, Id::call)) | |
5504 goto L1; // overload of opCall, therefore it's a call | |
5505 | |
5506 if (e1->op != TOKtype) | |
5507 error("%s %s does not overload ()", ad->kind(), ad->toChars()); | |
5508 /* It's a struct literal | |
5509 */ | |
5510 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments); | |
5511 e = e->semantic(sc); | |
5512 e->type = e1->type; // in case e1->type was a typedef | |
5513 return e; | |
5514 } | |
5515 else if (t1->ty == Tclass) | |
5516 { | |
5517 ad = ((TypeClass *)t1)->sym; | |
5518 goto L1; | |
5519 L1: | |
5520 // Rewrite as e1.call(arguments) | |
5521 Expression *e = new DotIdExp(loc, e1, Id::call); | |
5522 e = new CallExp(loc, e, arguments); | |
5523 e = e->semantic(sc); | |
5524 return e; | |
5525 } | |
5526 } | |
5527 | |
5528 arrayExpressionSemantic(arguments, sc); | |
5529 preFunctionArguments(loc, sc, arguments); | |
5530 | |
5531 if (e1->op == TOKdotvar && t1->ty == Tfunction || | |
5532 e1->op == TOKdottd) | |
5533 { | |
5534 DotVarExp *dve; | |
5535 DotTemplateExp *dte; | |
5536 AggregateDeclaration *ad; | |
5537 UnaExp *ue = (UnaExp *)(e1); | |
5538 | |
5539 if (e1->op == TOKdotvar) | |
5540 { // Do overload resolution | |
5541 dve = (DotVarExp *)(e1); | |
5542 | |
5543 f = dve->var->isFuncDeclaration(); | |
5544 assert(f); | |
5545 f = f->overloadResolve(loc, arguments); | |
5546 | |
5547 ad = f->toParent()->isAggregateDeclaration(); | |
5548 } | |
5549 else | |
5550 { dte = (DotTemplateExp *)(e1); | |
5551 TemplateDeclaration *td = dte->td; | |
5552 assert(td); | |
5553 if (!arguments) | |
5554 // Should fix deduceFunctionTemplate() so it works on NULL argument | |
5555 arguments = new Expressions(); | |
5556 f = td->deduceFunctionTemplate(sc, loc, NULL, arguments); | |
5557 if (!f) | |
5558 { type = Type::terror; | |
5559 return this; | |
5560 } | |
5561 ad = td->toParent()->isAggregateDeclaration(); | |
5562 } | |
5563 /* Now that we have the right function f, we need to get the | |
5564 * right 'this' pointer if f is in an outer class, but our | |
5565 * existing 'this' pointer is in an inner class. | |
5566 * This code is analogous to that used for variables | |
5567 * in DotVarExp::semantic(). | |
5568 */ | |
5569 L10: | |
5570 Type *t = ue->e1->type->toBasetype(); | |
5571 if (f->needThis() && ad && | |
5572 !(t->ty == Tpointer && t->next->ty == Tstruct && | |
5573 ((TypeStruct *)t->next)->sym == ad) && | |
5574 !(t->ty == Tstruct && ((TypeStruct *)t)->sym == ad) | |
5575 ) | |
5576 { | |
5577 ClassDeclaration *cd = ad->isClassDeclaration(); | |
5578 ClassDeclaration *tcd = t->isClassHandle(); | |
5579 | |
5580 if (!cd || !tcd || | |
5581 !(tcd == cd || cd->isBaseOf(tcd, NULL)) | |
5582 ) | |
5583 { | |
5584 if (tcd && tcd->isNested()) | |
5585 { // Try again with outer scope | |
5586 | |
5587 ue->e1 = new DotVarExp(loc, ue->e1, tcd->vthis); | |
5588 ue->e1 = ue->e1->semantic(sc); | |
5589 goto L10; | |
5590 } | |
5591 #ifdef DEBUG | |
5592 printf("1: "); | |
5593 #endif | |
5594 error("this for %s needs to be type %s not type %s", | |
5595 f->toChars(), ad->toChars(), t->toChars()); | |
5596 } | |
5597 } | |
5598 | |
5599 checkDeprecated(sc, f); | |
5600 accessCheck(loc, sc, ue->e1, f); | |
5601 if (!f->needThis()) | |
5602 { | |
5603 VarExp *ve = new VarExp(loc, f); | |
5604 e1 = new CommaExp(loc, ue->e1, ve); | |
5605 e1->type = f->type; | |
5606 } | |
5607 else | |
5608 { | |
5609 if (e1->op == TOKdotvar) | |
5610 dve->var = f; | |
5611 else | |
5612 e1 = new DotVarExp(loc, dte->e1, f); | |
5613 e1->type = f->type; | |
5614 | |
5615 // See if we need to adjust the 'this' pointer | |
5616 AggregateDeclaration *ad = f->isThis(); | |
5617 ClassDeclaration *cd = ue->e1->type->isClassHandle(); | |
5618 if (ad && cd && ad->isClassDeclaration() && ad != cd && | |
5619 ue->e1->op != TOKsuper) | |
5620 { | |
5621 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type); | |
5622 ue->e1 = ue->e1->semantic(sc); | |
5623 } | |
5624 } | |
5625 t1 = e1->type; | |
5626 } | |
5627 else if (e1->op == TOKsuper) | |
5628 { | |
5629 // Base class constructor call | |
5630 ClassDeclaration *cd = NULL; | |
5631 | |
5632 if (sc->func) | |
5633 cd = sc->func->toParent()->isClassDeclaration(); | |
5634 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) | |
5635 { | |
5636 error("super class constructor call must be in a constructor"); | |
5637 type = Type::terror; | |
5638 return this; | |
5639 } | |
5640 else | |
5641 { | |
5642 f = cd->baseClass->ctor; | |
5643 if (!f) | |
5644 { error("no super class constructor for %s", cd->baseClass->toChars()); | |
5645 type = Type::terror; | |
5646 return this; | |
5647 } | |
5648 else | |
5649 { | |
5650 #if 0 | |
5651 if (sc->callSuper & (CSXthis | CSXsuper)) | |
5652 error("reference to this before super()"); | |
5653 #endif | |
5654 if (sc->noctor || sc->callSuper & CSXlabel) | |
5655 error("constructor calls not allowed in loops or after labels"); | |
5656 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
5657 error("multiple constructor calls"); | |
5658 sc->callSuper |= CSXany_ctor | CSXsuper_ctor; | |
5659 | |
5660 f = f->overloadResolve(loc, arguments); | |
5661 checkDeprecated(sc, f); | |
5662 e1 = new DotVarExp(e1->loc, e1, f); | |
5663 e1 = e1->semantic(sc); | |
5664 t1 = e1->type; | |
5665 } | |
5666 } | |
5667 } | |
5668 else if (e1->op == TOKthis) | |
5669 { | |
5670 // same class constructor call | |
5671 ClassDeclaration *cd = NULL; | |
5672 | |
5673 if (sc->func) | |
5674 cd = sc->func->toParent()->isClassDeclaration(); | |
5675 if (!cd || !sc->func->isCtorDeclaration()) | |
5676 { | |
5677 error("class constructor call must be in a constructor"); | |
5678 type = Type::terror; | |
5679 return this; | |
5680 } | |
5681 else | |
5682 { | |
5683 #if 0 | |
5684 if (sc->callSuper & (CSXthis | CSXsuper)) | |
5685 error("reference to this before super()"); | |
5686 #endif | |
5687 if (sc->noctor || sc->callSuper & CSXlabel) | |
5688 error("constructor calls not allowed in loops or after labels"); | |
5689 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
5690 error("multiple constructor calls"); | |
5691 sc->callSuper |= CSXany_ctor | CSXthis_ctor; | |
5692 | |
5693 f = cd->ctor; | |
5694 f = f->overloadResolve(loc, arguments); | |
5695 checkDeprecated(sc, f); | |
5696 e1 = new DotVarExp(e1->loc, e1, f); | |
5697 e1 = e1->semantic(sc); | |
5698 t1 = e1->type; | |
5699 | |
5700 // BUG: this should really be done by checking the static | |
5701 // call graph | |
5702 if (f == sc->func) | |
5703 error("cyclic constructor call"); | |
5704 } | |
5705 } | |
5706 else if (!t1) | |
5707 { | |
5708 error("function expected before (), not '%s'", e1->toChars()); | |
5709 type = Type::terror; | |
5710 return this; | |
5711 } | |
5712 else if (t1->ty != Tfunction) | |
5713 { | |
5714 if (t1->ty == Tdelegate) | |
5715 { | |
5716 assert(t1->next->ty == Tfunction); | |
5717 tf = (TypeFunction *)(t1->next); | |
5718 goto Lcheckargs; | |
5719 } | |
5720 else if (t1->ty == Tpointer && t1->next->ty == Tfunction) | |
5721 { Expression *e; | |
5722 | |
5723 e = new PtrExp(loc, e1); | |
5724 t1 = t1->next; | |
5725 e->type = t1; | |
5726 e1 = e; | |
5727 } | |
5728 else if (e1->op == TOKtemplate) | |
5729 { | |
5730 TemplateExp *te = (TemplateExp *)e1; | |
5731 f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments); | |
5732 if (!f) | |
5733 { type = Type::terror; | |
5734 return this; | |
5735 } | |
5736 if (f->needThis() && hasThis(sc)) | |
5737 { | |
5738 // Supply an implicit 'this', as in | |
5739 // this.ident | |
5740 | |
5741 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td); | |
5742 goto Lagain; | |
5743 } | |
5744 | |
5745 e1 = new VarExp(loc, f); | |
5746 goto Lagain; | |
5747 } | |
5748 else | |
5749 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); | |
5750 type = Type::terror; | |
5751 return this; | |
5752 } | |
5753 } | |
5754 else if (e1->op == TOKvar) | |
5755 { | |
5756 // Do overload resolution | |
5757 VarExp *ve = (VarExp *)e1; | |
5758 | |
5759 f = ve->var->isFuncDeclaration(); | |
5760 assert(f); | |
5761 | |
5762 // Look to see if f is really a function template | |
5763 if (0 && !istemp && f->parent) | |
5764 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
5765 | |
5766 if (ti && | |
5767 (ti->name == f->ident || | |
5768 ti->toAlias()->ident == f->ident) | |
5769 && | |
5770 ti->tempdecl) | |
5771 { | |
5772 /* This is so that one can refer to the enclosing | |
5773 * template, even if it has the same name as a member | |
5774 * of the template, if it has a !(arguments) | |
5775 */ | |
5776 TemplateDeclaration *tempdecl = ti->tempdecl; | |
5777 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
5778 tempdecl = tempdecl->overroot; // then get the start | |
5779 e1 = new TemplateExp(loc, tempdecl); | |
5780 istemp = 1; | |
5781 goto Lagain; | |
5782 } | |
5783 } | |
5784 | |
5785 f = f->overloadResolve(loc, arguments); | |
5786 checkDeprecated(sc, f); | |
5787 | |
5788 if (f->needThis() && hasThis(sc)) | |
5789 { | |
5790 // Supply an implicit 'this', as in | |
5791 // this.ident | |
5792 | |
5793 e1 = new DotVarExp(loc, new ThisExp(loc), f); | |
5794 goto Lagain; | |
5795 } | |
5796 | |
5797 accessCheck(loc, sc, NULL, f); | |
5798 | |
5799 ve->var = f; | |
5800 ve->type = f->type; | |
5801 t1 = f->type; | |
5802 } | |
5803 assert(t1->ty == Tfunction); | |
5804 tf = (TypeFunction *)(t1); | |
5805 | |
5806 Lcheckargs: | |
5807 assert(tf->ty == Tfunction); | |
5808 type = tf->next; | |
5809 | |
5810 if (!arguments) | |
5811 arguments = new Expressions(); | |
5812 functionArguments(loc, sc, tf, arguments); | |
5813 | |
5814 assert(type); | |
5815 | |
5816 if (f && f->tintro) | |
5817 { | |
5818 Type *t = type; | |
5819 int offset = 0; | |
5820 | |
5821 if (f->tintro->next->isBaseOf(t, &offset) && offset) | |
5822 { | |
5823 type = f->tintro->next; | |
5824 return castTo(sc, t); | |
5825 } | |
5826 } | |
5827 | |
5828 return this; | |
5829 } | |
5830 | |
5831 int CallExp::checkSideEffect(int flag) | |
5832 { | |
5833 return 1; | |
5834 } | |
5835 | |
5836 Expression *CallExp::toLvalue(Scope *sc, Expression *e) | |
5837 { | |
5838 if (type->toBasetype()->ty == Tstruct) | |
5839 return this; | |
5840 else | |
5841 return Expression::toLvalue(sc, e); | |
5842 } | |
5843 | |
5844 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5845 { int i; | |
5846 | |
5847 expToCBuffer(buf, hgs, e1, precedence[op]); | |
5848 buf->writeByte('('); | |
5849 argsToCBuffer(buf, arguments, hgs); | |
5850 buf->writeByte(')'); | |
5851 } | |
5852 | |
5853 | |
5854 /************************************************************/ | |
5855 | |
5856 AddrExp::AddrExp(Loc loc, Expression *e) | |
5857 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) | |
5858 { | |
5859 } | |
5860 | |
5861 Expression *AddrExp::semantic(Scope *sc) | |
5862 { | |
5863 #if LOGSEMANTIC | |
5864 printf("AddrExp::semantic('%s')\n", toChars()); | |
5865 #endif | |
5866 if (!type) | |
5867 { | |
5868 UnaExp::semantic(sc); | |
5869 e1 = e1->toLvalue(sc, NULL); | |
5870 if (!e1->type) | |
5871 { | |
5872 error("cannot take address of %s", e1->toChars()); | |
5873 type = Type::tint32; | |
5874 return this; | |
5875 } | |
5876 type = e1->type->pointerTo(); | |
5877 | |
5878 // See if this should really be a delegate | |
5879 if (e1->op == TOKdotvar) | |
5880 { | |
5881 DotVarExp *dve = (DotVarExp *)e1; | |
5882 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
5883 | |
5884 if (f) | |
5885 { Expression *e; | |
5886 | |
5887 e = new DelegateExp(loc, dve->e1, f); | |
5888 e = e->semantic(sc); | |
5889 return e; | |
5890 } | |
5891 } | |
5892 else if (e1->op == TOKvar) | |
5893 { | |
5894 VarExp *dve = (VarExp *)e1; | |
5895 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
5896 VarDeclaration *v = dve->var->isVarDeclaration(); | |
5897 | |
5898 if (f && f->isNested()) | |
5899 { Expression *e; | |
5900 | |
5901 e = new DelegateExp(loc, e1, f); | |
5902 e = e->semantic(sc); | |
5903 return e; | |
5904 } | |
5905 else if (v) | |
5906 { | |
5907 v->needsStorage = true; | |
5908 } | |
5909 } | |
5910 else if (e1->op == TOKarray) | |
5911 { | |
5912 if (e1->type->toBasetype()->ty == Tbit) | |
5913 error("cannot take address of bit in array"); | |
5914 } | |
5915 return optimize(WANTvalue); | |
5916 } | |
5917 return this; | |
5918 } | |
5919 | |
5920 /************************************************************/ | |
5921 | |
5922 PtrExp::PtrExp(Loc loc, Expression *e) | |
5923 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
5924 { | |
5925 if (e->type) | |
5926 type = e->type->next; | |
5927 } | |
5928 | |
5929 PtrExp::PtrExp(Loc loc, Expression *e, Type *t) | |
5930 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
5931 { | |
5932 type = t; | |
5933 } | |
5934 | |
5935 Expression *PtrExp::semantic(Scope *sc) | |
5936 { Type *tb; | |
5937 | |
5938 #if LOGSEMANTIC | |
5939 printf("PtrExp::semantic('%s')\n", toChars()); | |
5940 #endif | |
5941 UnaExp::semantic(sc); | |
5942 e1 = resolveProperties(sc, e1); | |
5943 if (type) | |
5944 return this; | |
5945 if (!e1->type) | |
5946 printf("PtrExp::semantic('%s')\n", toChars()); | |
5947 tb = e1->type->toBasetype(); | |
5948 switch (tb->ty) | |
5949 { | |
5950 case Tpointer: | |
5951 type = tb->next; | |
5952 if (type->isbit()) | |
5953 { Expression *e; | |
5954 | |
5955 // Rewrite *p as p[0] | |
5956 e = new IndexExp(loc, e1, new IntegerExp(0)); | |
5957 return e->semantic(sc); | |
5958 } | |
5959 break; | |
5960 | |
5961 case Tsarray: | |
5962 case Tarray: | |
5963 type = tb->next; | |
5964 e1 = e1->castTo(sc, type->pointerTo()); | |
5965 break; | |
5966 | |
5967 default: | |
5968 error("can only * a pointer, not a '%s'", e1->type->toChars()); | |
5969 type = Type::tint32; | |
5970 break; | |
5971 } | |
5972 rvalue(); | |
5973 return this; | |
5974 } | |
5975 | |
5976 Expression *PtrExp::toLvalue(Scope *sc, Expression *e) | |
5977 { | |
5978 #if 0 | |
5979 tym = tybasic(e1->ET->Tty); | |
5980 if (!(tyscalar(tym) || | |
5981 tym == TYstruct || | |
5982 tym == TYarray && e->Eoper == TOKaddr)) | |
5983 synerr(EM_lvalue); // lvalue expected | |
5984 #endif | |
5985 return this; | |
5986 } | |
5987 | |
5988 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5989 { | |
5990 buf->writeByte('*'); | |
5991 expToCBuffer(buf, hgs, e1, precedence[op]); | |
5992 } | |
5993 | |
5994 /************************************************************/ | |
5995 | |
5996 NegExp::NegExp(Loc loc, Expression *e) | |
5997 : UnaExp(loc, TOKneg, sizeof(NegExp), e) | |
5998 { | |
5999 } | |
6000 | |
6001 Expression *NegExp::semantic(Scope *sc) | |
6002 { Expression *e; | |
6003 | |
6004 #if LOGSEMANTIC | |
6005 printf("NegExp::semantic('%s')\n", toChars()); | |
6006 #endif | |
6007 if (!type) | |
6008 { | |
6009 UnaExp::semantic(sc); | |
6010 e1 = resolveProperties(sc, e1); | |
6011 e = op_overload(sc); | |
6012 if (e) | |
6013 return e; | |
6014 | |
6015 e1->checkNoBool(); | |
6016 e1->checkArithmetic(); | |
6017 type = e1->type; | |
6018 } | |
6019 return this; | |
6020 } | |
6021 | |
6022 /************************************************************/ | |
6023 | |
6024 UAddExp::UAddExp(Loc loc, Expression *e) | |
6025 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e) | |
6026 { | |
6027 } | |
6028 | |
6029 Expression *UAddExp::semantic(Scope *sc) | |
6030 { Expression *e; | |
6031 | |
6032 #if LOGSEMANTIC | |
6033 printf("UAddExp::semantic('%s')\n", toChars()); | |
6034 #endif | |
6035 assert(!type); | |
6036 UnaExp::semantic(sc); | |
6037 e1 = resolveProperties(sc, e1); | |
6038 e = op_overload(sc); | |
6039 if (e) | |
6040 return e; | |
6041 e1->checkNoBool(); | |
6042 e1->checkArithmetic(); | |
6043 return e1; | |
6044 } | |
6045 | |
6046 /************************************************************/ | |
6047 | |
6048 ComExp::ComExp(Loc loc, Expression *e) | |
6049 : UnaExp(loc, TOKtilde, sizeof(ComExp), e) | |
6050 { | |
6051 } | |
6052 | |
6053 Expression *ComExp::semantic(Scope *sc) | |
6054 { Expression *e; | |
6055 | |
6056 if (!type) | |
6057 { | |
6058 UnaExp::semantic(sc); | |
6059 e1 = resolveProperties(sc, e1); | |
6060 e = op_overload(sc); | |
6061 if (e) | |
6062 return e; | |
6063 | |
6064 e1->checkNoBool(); | |
6065 e1 = e1->checkIntegral(); | |
6066 type = e1->type; | |
6067 } | |
6068 return this; | |
6069 } | |
6070 | |
6071 /************************************************************/ | |
6072 | |
6073 NotExp::NotExp(Loc loc, Expression *e) | |
6074 : UnaExp(loc, TOKnot, sizeof(NotExp), e) | |
6075 { | |
6076 } | |
6077 | |
6078 Expression *NotExp::semantic(Scope *sc) | |
6079 { | |
6080 UnaExp::semantic(sc); | |
6081 e1 = resolveProperties(sc, e1); | |
6082 e1 = e1->checkToBoolean(); | |
6083 type = Type::tboolean; | |
6084 return this; | |
6085 } | |
6086 | |
6087 int NotExp::isBit() | |
6088 { | |
6089 return TRUE; | |
6090 } | |
6091 | |
6092 | |
6093 | |
6094 /************************************************************/ | |
6095 | |
6096 BoolExp::BoolExp(Loc loc, Expression *e, Type *t) | |
6097 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e) | |
6098 { | |
6099 type = t; | |
6100 } | |
6101 | |
6102 Expression *BoolExp::semantic(Scope *sc) | |
6103 { | |
6104 UnaExp::semantic(sc); | |
6105 e1 = resolveProperties(sc, e1); | |
6106 e1 = e1->checkToBoolean(); | |
6107 type = Type::tboolean; | |
6108 return this; | |
6109 } | |
6110 | |
6111 int BoolExp::isBit() | |
6112 { | |
6113 return TRUE; | |
6114 } | |
6115 | |
6116 /************************************************************/ | |
6117 | |
6118 DeleteExp::DeleteExp(Loc loc, Expression *e) | |
6119 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e) | |
6120 { | |
6121 } | |
6122 | |
6123 Expression *DeleteExp::semantic(Scope *sc) | |
6124 { | |
6125 Type *tb; | |
6126 | |
6127 UnaExp::semantic(sc); | |
6128 e1 = resolveProperties(sc, e1); | |
6129 e1 = e1->toLvalue(sc, NULL); | |
6130 type = Type::tvoid; | |
6131 | |
6132 tb = e1->type->toBasetype(); | |
6133 switch (tb->ty) | |
6134 { case Tclass: | |
6135 { TypeClass *tc = (TypeClass *)tb; | |
6136 ClassDeclaration *cd = tc->sym; | |
6137 | |
6138 if (cd->isCOMinterface()) | |
6139 { /* Because COM classes are deleted by IUnknown.Release() | |
6140 */ | |
6141 error("cannot delete instance of COM interface %s", cd->toChars()); | |
6142 } | |
6143 break; | |
6144 } | |
6145 case Tpointer: | |
6146 tb = tb->next->toBasetype(); | |
6147 if (tb->ty == Tstruct) | |
6148 { | |
6149 TypeStruct *ts = (TypeStruct *)tb; | |
6150 StructDeclaration *sd = ts->sym; | |
6151 FuncDeclaration *f = sd->aggDelete; | |
6152 | |
6153 if (f) | |
6154 { | |
6155 Type *tpv = Type::tvoid->pointerTo(); | |
6156 | |
6157 Expression *e = e1->castTo(sc, tpv); | |
6158 Expression *ec = new VarExp(loc, f); | |
6159 e = new CallExp(loc, ec, e); | |
6160 return e->semantic(sc); | |
6161 } | |
6162 } | |
6163 break; | |
6164 | |
6165 case Tarray: | |
6166 break; | |
6167 | |
6168 default: | |
6169 if (e1->op == TOKindex) | |
6170 { | |
6171 IndexExp *ae = (IndexExp *)(e1); | |
6172 Type *tb1 = ae->e1->type->toBasetype(); | |
6173 if (tb1->ty == Taarray) | |
6174 break; | |
6175 } | |
6176 error("cannot delete type %s", e1->type->toChars()); | |
6177 break; | |
6178 } | |
6179 | |
6180 if (e1->op == TOKindex) | |
6181 { | |
6182 IndexExp *ae = (IndexExp *)(e1); | |
6183 Type *tb1 = ae->e1->type->toBasetype(); | |
6184 if (tb1->ty == Taarray) | |
6185 { if (!global.params.useDeprecated) | |
6186 error("delete aa[key] deprecated, use aa.remove(key)"); | |
6187 } | |
6188 } | |
6189 | |
6190 return this; | |
6191 } | |
6192 | |
6193 int DeleteExp::checkSideEffect(int flag) | |
6194 { | |
6195 return 1; | |
6196 } | |
6197 | |
6198 Expression *DeleteExp::checkToBoolean() | |
6199 { | |
6200 error("delete does not give a boolean result"); | |
6201 return this; | |
6202 } | |
6203 | |
6204 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6205 { | |
6206 buf->writestring("delete "); | |
6207 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6208 } | |
6209 | |
6210 /************************************************************/ | |
6211 | |
6212 CastExp::CastExp(Loc loc, Expression *e, Type *t) | |
6213 : UnaExp(loc, TOKcast, sizeof(CastExp), e) | |
6214 { | |
6215 to = t; | |
6216 } | |
6217 | |
6218 Expression *CastExp::syntaxCopy() | |
6219 { | |
6220 return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy()); | |
6221 } | |
6222 | |
6223 | |
6224 Expression *CastExp::semantic(Scope *sc) | |
6225 { Expression *e; | |
6226 BinExp *b; | |
6227 UnaExp *u; | |
6228 | |
6229 #if LOGSEMANTIC | |
6230 printf("CastExp::semantic('%s')\n", toChars()); | |
6231 #endif | |
6232 | |
6233 //static int x; assert(++x < 10); | |
6234 | |
6235 if (type) | |
6236 return this; | |
6237 UnaExp::semantic(sc); | |
6238 if (e1->type) // if not a tuple | |
6239 { | |
6240 e1 = resolveProperties(sc, e1); | |
6241 to = to->semantic(loc, sc); | |
6242 | |
6243 e = op_overload(sc); | |
6244 if (e) | |
6245 { | |
6246 return e->implicitCastTo(sc, to); | |
6247 } | |
6248 | |
6249 Type *tob = to->toBasetype(); | |
6250 if (tob->ty == Tstruct && | |
6251 !tob->equals(e1->type->toBasetype()) && | |
6252 ((TypeStruct *)to)->sym->search(0, Id::call, 0) | |
6253 ) | |
6254 { | |
6255 /* Look to replace: | |
6256 * cast(S)t | |
6257 * with: | |
6258 * S(t) | |
6259 */ | |
6260 | |
6261 // Rewrite as to.call(e1) | |
6262 e = new TypeExp(loc, to); | |
6263 e = new DotIdExp(loc, e, Id::call); | |
6264 e = new CallExp(loc, e, e1); | |
6265 e = e->semantic(sc); | |
6266 return e; | |
6267 } | |
6268 } | |
6269 e = e1->castTo(sc, to); | |
6270 return e; | |
6271 } | |
6272 | |
6273 int CastExp::checkSideEffect(int flag) | |
6274 { | |
6275 /* if not: | |
6276 * cast(void) | |
6277 * cast(classtype)func() | |
6278 */ | |
6279 if (!to->equals(Type::tvoid) && | |
6280 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass)) | |
6281 return Expression::checkSideEffect(flag); | |
6282 return 1; | |
6283 } | |
6284 | |
6285 void CastExp::checkEscape() | |
6286 { Type *tb = type->toBasetype(); | |
6287 if (tb->ty == Tarray && e1->op == TOKvar && | |
6288 e1->type->toBasetype()->ty == Tsarray) | |
6289 { VarExp *ve = (VarExp *)e1; | |
6290 VarDeclaration *v = ve->var->isVarDeclaration(); | |
6291 if (v) | |
6292 { | |
6293 if (!v->isDataseg() && !v->isParameter()) | |
6294 error("escaping reference to local %s", v->toChars()); | |
6295 } | |
6296 } | |
6297 } | |
6298 | |
6299 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6300 { | |
6301 buf->writestring("cast("); | |
6302 to->toCBuffer(buf, NULL, hgs); | |
6303 buf->writeByte(')'); | |
6304 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6305 } | |
6306 | |
6307 | |
6308 /************************************************************/ | |
6309 | |
6310 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) | |
6311 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) | |
6312 { | |
6313 this->upr = upr; | |
6314 this->lwr = lwr; | |
6315 lengthVar = NULL; | |
6316 } | |
6317 | |
6318 Expression *SliceExp::syntaxCopy() | |
6319 { | |
6320 Expression *lwr = NULL; | |
6321 if (this->lwr) | |
6322 lwr = this->lwr->syntaxCopy(); | |
6323 | |
6324 Expression *upr = NULL; | |
6325 if (this->upr) | |
6326 upr = this->upr->syntaxCopy(); | |
6327 | |
6328 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr); | |
6329 } | |
6330 | |
6331 Expression *SliceExp::semantic(Scope *sc) | |
6332 { Expression *e; | |
6333 AggregateDeclaration *ad; | |
6334 //FuncDeclaration *fd; | |
6335 ScopeDsymbol *sym; | |
6336 | |
6337 #if LOGSEMANTIC | |
6338 printf("SliceExp::semantic('%s')\n", toChars()); | |
6339 #endif | |
6340 if (type) | |
6341 return this; | |
6342 | |
6343 UnaExp::semantic(sc); | |
6344 e1 = resolveProperties(sc, e1); | |
6345 | |
6346 e = this; | |
6347 | |
6348 Type *t = e1->type->toBasetype(); | |
6349 if (t->ty == Tpointer) | |
6350 { | |
6351 if (!lwr || !upr) | |
6352 error("need upper and lower bound to slice pointer"); | |
6353 } | |
6354 else if (t->ty == Tarray) | |
6355 { | |
6356 } | |
6357 else if (t->ty == Tsarray) | |
6358 { | |
6359 } | |
6360 else if (t->ty == Tclass) | |
6361 { | |
6362 ad = ((TypeClass *)t)->sym; | |
6363 goto L1; | |
6364 } | |
6365 else if (t->ty == Tstruct) | |
6366 { | |
6367 ad = ((TypeStruct *)t)->sym; | |
6368 | |
6369 L1: | |
6370 if (search_function(ad, Id::slice)) | |
6371 { | |
6372 // Rewrite as e1.slice(lwr, upr) | |
6373 e = new DotIdExp(loc, e1, Id::slice); | |
6374 | |
6375 if (lwr) | |
6376 { | |
6377 assert(upr); | |
6378 e = new CallExp(loc, e, lwr, upr); | |
6379 } | |
6380 else | |
6381 { assert(!upr); | |
6382 e = new CallExp(loc, e); | |
6383 } | |
6384 e = e->semantic(sc); | |
6385 return e; | |
6386 } | |
6387 goto Lerror; | |
6388 } | |
6389 else if (t->ty == Ttuple) | |
6390 { | |
6391 if (!lwr && !upr) | |
6392 return e1; | |
6393 if (!lwr || !upr) | |
6394 { error("need upper and lower bound to slice tuple"); | |
6395 goto Lerror; | |
6396 } | |
6397 } | |
6398 else | |
6399 goto Lerror; | |
6400 | |
6401 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
6402 { | |
6403 sym = new ArrayScopeSymbol(this); | |
6404 sym->loc = loc; | |
6405 sym->parent = sc->scopesym; | |
6406 sc = sc->push(sym); | |
6407 } | |
6408 | |
6409 if (lwr) | |
6410 { lwr = lwr->semantic(sc); | |
6411 lwr = resolveProperties(sc, lwr); | |
6412 lwr = lwr->implicitCastTo(sc, Type::tsize_t); | |
6413 } | |
6414 if (upr) | |
6415 { upr = upr->semantic(sc); | |
6416 upr = resolveProperties(sc, upr); | |
6417 upr = upr->implicitCastTo(sc, Type::tsize_t); | |
6418 } | |
6419 | |
6420 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
6421 sc->pop(); | |
6422 | |
6423 if (t->ty == Ttuple) | |
6424 { | |
6425 lwr = lwr->optimize(WANTvalue); | |
6426 upr = upr->optimize(WANTvalue); | |
6427 uinteger_t i1 = lwr->toUInteger(); | |
6428 uinteger_t i2 = upr->toUInteger(); | |
6429 | |
6430 size_t length; | |
6431 TupleExp *te; | |
6432 TypeTuple *tup; | |
6433 | |
6434 if (e1->op == TOKtuple) // slicing an expression tuple | |
6435 { te = (TupleExp *)e1; | |
6436 length = te->exps->dim; | |
6437 } | |
6438 else if (e1->op == TOKtype) // slicing a type tuple | |
6439 { tup = (TypeTuple *)t; | |
6440 length = Argument::dim(tup->arguments); | |
6441 } | |
6442 else | |
6443 assert(0); | |
6444 | |
6445 if (i1 <= i2 && i2 <= length) | |
6446 { size_t j1 = (size_t) i1; | |
6447 size_t j2 = (size_t) i2; | |
6448 | |
6449 if (e1->op == TOKtuple) | |
6450 { Expressions *exps = new Expressions; | |
6451 exps->setDim(j2 - j1); | |
6452 for (size_t i = 0; i < j2 - j1; i++) | |
6453 { Expression *e = (Expression *)te->exps->data[j1 + i]; | |
6454 exps->data[i] = (void *)e; | |
6455 } | |
6456 e = new TupleExp(loc, exps); | |
6457 } | |
6458 else | |
6459 { Arguments *args = new Arguments; | |
6460 args->reserve(j2 - j1); | |
6461 for (size_t i = j1; i < j2; i++) | |
6462 { Argument *arg = Argument::getNth(tup->arguments, i); | |
6463 args->push(arg); | |
6464 } | |
6465 e = new TypeExp(e1->loc, new TypeTuple(args)); | |
6466 } | |
6467 e = e->semantic(sc); | |
6468 } | |
6469 else | |
6470 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6471 error("string slice [%llu .. %llu] is out of bounds", i1, i2); |
159 | 6472 e = e1; |
6473 } | |
6474 return e; | |
6475 } | |
6476 | |
6477 type = t->next->arrayOf(); | |
6478 return e; | |
6479 | |
6480 Lerror: | |
6481 char *s; | |
6482 if (t->ty == Tvoid) | |
6483 s = e1->toChars(); | |
6484 else | |
6485 s = t->toChars(); | |
6486 error("%s cannot be sliced with []", s); | |
6487 type = Type::terror; | |
6488 return e; | |
6489 } | |
6490 | |
6491 void SliceExp::checkEscape() | |
6492 { | |
6493 e1->checkEscape(); | |
6494 } | |
6495 | |
6496 Expression *SliceExp::toLvalue(Scope *sc, Expression *e) | |
6497 { | |
6498 return this; | |
6499 } | |
6500 | |
6501 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) | |
6502 { | |
6503 error("slice expression %s is not a modifiable lvalue", toChars()); | |
6504 return this; | |
6505 } | |
6506 | |
6507 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6508 { | |
6509 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6510 buf->writeByte('['); | |
6511 if (upr || lwr) | |
6512 { | |
6513 if (lwr) | |
6514 expToCBuffer(buf, hgs, lwr, PREC_assign); | |
6515 else | |
6516 buf->writeByte('0'); | |
6517 buf->writestring(".."); | |
6518 if (upr) | |
6519 expToCBuffer(buf, hgs, upr, PREC_assign); | |
6520 else | |
6521 buf->writestring("length"); // BUG: should be array.length | |
6522 } | |
6523 buf->writeByte(']'); | |
6524 } | |
6525 | |
6526 /********************** ArrayLength **************************************/ | |
6527 | |
6528 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) | |
6529 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1) | |
6530 { | |
6531 } | |
6532 | |
6533 Expression *ArrayLengthExp::semantic(Scope *sc) | |
6534 { Expression *e; | |
6535 | |
6536 #if LOGSEMANTIC | |
6537 printf("ArrayLengthExp::semantic('%s')\n", toChars()); | |
6538 #endif | |
6539 if (!type) | |
6540 { | |
6541 UnaExp::semantic(sc); | |
6542 e1 = resolveProperties(sc, e1); | |
6543 | |
6544 type = Type::tsize_t; | |
6545 } | |
6546 return this; | |
6547 } | |
6548 | |
6549 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6550 { | |
6551 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6552 buf->writestring(".length"); | |
6553 } | |
6554 | |
6555 /*********************** ArrayExp *************************************/ | |
6556 | |
6557 // e1 [ i1, i2, i3, ... ] | |
6558 | |
6559 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args) | |
6560 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) | |
6561 { | |
6562 arguments = args; | |
6563 } | |
6564 | |
6565 Expression *ArrayExp::syntaxCopy() | |
6566 { | |
6567 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
6568 } | |
6569 | |
6570 Expression *ArrayExp::semantic(Scope *sc) | |
6571 { Expression *e; | |
6572 Type *t1; | |
6573 | |
6574 #if LOGSEMANTIC | |
6575 printf("ArrayExp::semantic('%s')\n", toChars()); | |
6576 #endif | |
6577 UnaExp::semantic(sc); | |
6578 e1 = resolveProperties(sc, e1); | |
6579 | |
6580 t1 = e1->type->toBasetype(); | |
6581 if (t1->ty != Tclass && t1->ty != Tstruct) | |
6582 { // Convert to IndexExp | |
6583 if (arguments->dim != 1) | |
6584 error("only one index allowed to index %s", t1->toChars()); | |
6585 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]); | |
6586 return e->semantic(sc); | |
6587 } | |
6588 | |
6589 // Run semantic() on each argument | |
6590 for (size_t i = 0; i < arguments->dim; i++) | |
6591 { e = (Expression *)arguments->data[i]; | |
6592 | |
6593 e = e->semantic(sc); | |
6594 if (!e->type) | |
6595 error("%s has no value", e->toChars()); | |
6596 arguments->data[i] = (void *)e; | |
6597 } | |
6598 | |
6599 expandTuples(arguments); | |
6600 assert(arguments && arguments->dim); | |
6601 | |
6602 e = op_overload(sc); | |
6603 if (!e) | |
6604 { error("no [] operator overload for type %s", e1->type->toChars()); | |
6605 e = e1; | |
6606 } | |
6607 return e; | |
6608 } | |
6609 | |
6610 | |
6611 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e) | |
6612 { | |
6613 if (type && type->toBasetype()->ty == Tvoid) | |
6614 error("voids have no value"); | |
6615 return this; | |
6616 } | |
6617 | |
6618 | |
6619 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6620 { int i; | |
6621 | |
6622 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6623 buf->writeByte('['); | |
6624 argsToCBuffer(buf, arguments, hgs); | |
6625 buf->writeByte(']'); | |
6626 } | |
6627 | |
6628 /************************* DotExp ***********************************/ | |
6629 | |
6630 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2) | |
6631 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2) | |
6632 { | |
6633 } | |
6634 | |
6635 Expression *DotExp::semantic(Scope *sc) | |
6636 { | |
6637 #if LOGSEMANTIC | |
6638 printf("DotExp::semantic('%s')\n", toChars()); | |
6639 if (type) printf("\ttype = %s\n", type->toChars()); | |
6640 #endif | |
6641 e1 = e1->semantic(sc); | |
6642 e2 = e2->semantic(sc); | |
6643 if (e2->op == TOKimport) | |
6644 { | |
6645 ScopeExp *se = (ScopeExp *)e2; | |
6646 TemplateDeclaration *td = se->sds->isTemplateDeclaration(); | |
6647 if (td) | |
6648 { Expression *e = new DotTemplateExp(loc, e1, td); | |
6649 e = e->semantic(sc); | |
6650 return e; | |
6651 } | |
6652 } | |
6653 if (!type) | |
6654 type = e2->type; | |
6655 return this; | |
6656 } | |
6657 | |
6658 | |
6659 /************************* CommaExp ***********************************/ | |
6660 | |
6661 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2) | |
6662 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2) | |
6663 { | |
6664 } | |
6665 | |
6666 Expression *CommaExp::semantic(Scope *sc) | |
6667 { | |
6668 if (!type) | |
6669 { BinExp::semanticp(sc); | |
6670 type = e2->type; | |
6671 } | |
6672 return this; | |
6673 } | |
6674 | |
6675 void CommaExp::checkEscape() | |
6676 { | |
6677 e2->checkEscape(); | |
6678 } | |
6679 | |
6680 Expression *CommaExp::toLvalue(Scope *sc, Expression *e) | |
6681 { | |
6682 e2 = e2->toLvalue(sc, NULL); | |
6683 return this; | |
6684 } | |
6685 | |
6686 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e) | |
6687 { | |
6688 e2 = e2->modifiableLvalue(sc, e); | |
6689 return this; | |
6690 } | |
6691 | |
6692 int CommaExp::isBool(int result) | |
6693 { | |
6694 return e2->isBool(result); | |
6695 } | |
6696 | |
6697 int CommaExp::checkSideEffect(int flag) | |
6698 { | |
6699 if (flag == 2) | |
6700 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
6701 else | |
6702 { | |
6703 // Don't check e1 until we cast(void) the a,b code generation | |
6704 return e2->checkSideEffect(flag); | |
6705 } | |
6706 } | |
6707 | |
6708 /************************** IndexExp **********************************/ | |
6709 | |
6710 // e1 [ e2 ] | |
6711 | |
6712 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) | |
6713 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) | |
6714 { | |
6715 //printf("IndexExp::IndexExp('%s')\n", toChars()); | |
6716 lengthVar = NULL; | |
6717 modifiable = 0; // assume it is an rvalue | |
6718 } | |
6719 | |
6720 Expression *IndexExp::semantic(Scope *sc) | |
6721 { Expression *e; | |
6722 BinExp *b; | |
6723 UnaExp *u; | |
6724 Type *t1; | |
6725 ScopeDsymbol *sym; | |
6726 | |
6727 #if LOGSEMANTIC | |
6728 printf("IndexExp::semantic('%s')\n", toChars()); | |
6729 #endif | |
6730 if (type) | |
6731 return this; | |
6732 if (!e1->type) | |
6733 e1 = e1->semantic(sc); | |
6734 assert(e1->type); // semantic() should already be run on it | |
6735 e = this; | |
6736 | |
6737 // Note that unlike C we do not implement the int[ptr] | |
6738 | |
6739 t1 = e1->type->toBasetype(); | |
6740 | |
6741 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
6742 { // Create scope for 'length' variable | |
6743 sym = new ArrayScopeSymbol(this); | |
6744 sym->loc = loc; | |
6745 sym->parent = sc->scopesym; | |
6746 sc = sc->push(sym); | |
6747 } | |
6748 | |
6749 e2 = e2->semantic(sc); | |
6750 if (!e2->type) | |
6751 { | |
6752 error("%s has no value", e2->toChars()); | |
6753 e2->type = Type::terror; | |
6754 } | |
6755 e2 = resolveProperties(sc, e2); | |
6756 | |
6757 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
6758 sc = sc->pop(); | |
6759 | |
6760 switch (t1->ty) | |
6761 { | |
6762 case Tpointer: | |
6763 case Tarray: | |
6764 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
6765 e->type = t1->next; | |
6766 break; | |
6767 | |
6768 case Tsarray: | |
6769 { | |
6770 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
6771 | |
6772 TypeSArray *tsa = (TypeSArray *)t1; | |
6773 | |
6774 #if 0 // Don't do now, because it might be short-circuit evaluated | |
6775 // Do compile time array bounds checking if possible | |
6776 e2 = e2->optimize(WANTvalue); | |
6777 if (e2->op == TOKint64) | |
6778 { | |
6779 integer_t index = e2->toInteger(); | |
6780 integer_t length = tsa->dim->toInteger(); | |
6781 if (index < 0 || index >= length) | |
6782 error("array index [%lld] is outside array bounds [0 .. %lld]", | |
6783 index, length); | |
6784 } | |
6785 #endif | |
6786 e->type = t1->next; | |
6787 break; | |
6788 } | |
6789 | |
6790 case Taarray: | |
6791 { TypeAArray *taa = (TypeAArray *)t1; | |
6792 | |
6793 e2 = e2->implicitCastTo(sc, taa->index); // type checking | |
6794 e2 = e2->implicitCastTo(sc, taa->key); // actual argument type | |
6795 type = taa->next; | |
6796 break; | |
6797 } | |
6798 | |
6799 case Ttuple: | |
6800 { | |
6801 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
6802 e2 = e2->optimize(WANTvalue); | |
6803 uinteger_t index = e2->toUInteger(); | |
6804 size_t length; | |
6805 TupleExp *te; | |
6806 TypeTuple *tup; | |
6807 | |
6808 if (e1->op == TOKtuple) | |
6809 { te = (TupleExp *)e1; | |
6810 length = te->exps->dim; | |
6811 } | |
6812 else if (e1->op == TOKtype) | |
6813 { | |
6814 tup = (TypeTuple *)t1; | |
6815 length = Argument::dim(tup->arguments); | |
6816 } | |
6817 else | |
6818 assert(0); | |
6819 | |
6820 if (index < length) | |
6821 { | |
6822 | |
6823 if (e1->op == TOKtuple) | |
6824 e = (Expression *)te->exps->data[(size_t)index]; | |
6825 else | |
6826 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type); | |
6827 } | |
6828 else | |
6829 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6830 error("array index [%llu] is outside array bounds [0 .. %"PRIuSIZE"]", |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6831 index, length); |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6832 e = e1; |
159 | 6833 } |
6834 break; | |
6835 } | |
6836 | |
6837 default: | |
6838 error("%s must be an array or pointer type, not %s", | |
6839 e1->toChars(), e1->type->toChars()); | |
6840 type = Type::tint32; | |
6841 break; | |
6842 } | |
6843 return e; | |
6844 } | |
6845 | |
6846 Expression *IndexExp::toLvalue(Scope *sc, Expression *e) | |
6847 { | |
6848 // if (type && type->toBasetype()->ty == Tvoid) | |
6849 // error("voids have no value"); | |
6850 return this; | |
6851 } | |
6852 | |
6853 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) | |
6854 { | |
6855 //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); | |
6856 modifiable = 1; | |
6857 if (e1->op == TOKstring) | |
6858 error("string literals are immutable"); | |
6859 if (e1->type->toBasetype()->ty == Taarray) | |
6860 e1 = e1->modifiableLvalue(sc, e1); | |
6861 return toLvalue(sc, e); | |
6862 } | |
6863 | |
6864 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6865 { | |
6866 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6867 buf->writeByte('['); | |
6868 expToCBuffer(buf, hgs, e2, PREC_assign); | |
6869 buf->writeByte(']'); | |
6870 } | |
6871 | |
6872 | |
6873 /************************* PostExp ***********************************/ | |
6874 | |
6875 PostExp::PostExp(enum TOK op, Loc loc, Expression *e) | |
6876 : BinExp(loc, op, sizeof(PostExp), e, | |
6877 new IntegerExp(loc, 1, Type::tint32)) | |
6878 { | |
6879 } | |
6880 | |
6881 Expression *PostExp::semantic(Scope *sc) | |
6882 { Expression *e = this; | |
6883 | |
6884 if (!type) | |
6885 { | |
6886 BinExp::semantic(sc); | |
6887 e2 = resolveProperties(sc, e2); | |
6888 | |
6889 e = op_overload(sc); | |
6890 if (e) | |
6891 return e; | |
6892 | |
6893 e = this; | |
6894 e1 = e1->modifiableLvalue(sc, e1); | |
6895 e1->checkScalar(); | |
6896 e1->checkNoBool(); | |
6897 if (e1->type->ty == Tpointer) | |
6898 e = scaleFactor(sc); | |
6899 else | |
6900 e2 = e2->castTo(sc, e1->type); | |
6901 e->type = e1->type; | |
6902 } | |
6903 return e; | |
6904 } | |
6905 | |
6906 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6907 { | |
6908 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6909 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--"); | |
6910 } | |
6911 | |
6912 /************************************************************/ | |
6913 | |
6914 /* Can be TOKconstruct too */ | |
6915 | |
6916 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) | |
6917 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) | |
6918 { | |
6919 ismemset = 0; | |
6920 } | |
6921 | |
6922 Expression *AssignExp::semantic(Scope *sc) | |
6923 { Type *t1; | |
6924 Expression *e1old = e1; | |
6925 | |
6926 #if LOGSEMANTIC | |
6927 printf("AssignExp::semantic('%s')\n", toChars()); | |
6928 #endif | |
6929 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
6930 | |
6931 /* Look for operator overloading of a[i]=value. | |
6932 * Do it before semantic() otherwise the a[i] will have been | |
6933 * converted to a.opIndex() already. | |
6934 */ | |
6935 if (e1->op == TOKarray) | |
6936 { Type *t1; | |
6937 ArrayExp *ae = (ArrayExp *)e1; | |
6938 AggregateDeclaration *ad; | |
6939 Identifier *id = Id::index; | |
6940 | |
6941 ae->e1 = ae->e1->semantic(sc); | |
6942 t1 = ae->e1->type->toBasetype(); | |
6943 if (t1->ty == Tstruct) | |
6944 { | |
6945 ad = ((TypeStruct *)t1)->sym; | |
6946 goto L1; | |
6947 } | |
6948 else if (t1->ty == Tclass) | |
6949 { | |
6950 ad = ((TypeClass *)t1)->sym; | |
6951 L1: | |
6952 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) | |
6953 if (search_function(ad, Id::indexass)) | |
6954 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); | |
6955 Expressions *a = (Expressions *)ae->arguments->copy(); | |
6956 | |
6957 a->insert(0, e2); | |
6958 e = new CallExp(loc, e, a); | |
6959 e = e->semantic(sc); | |
6960 return e; | |
6961 } | |
6962 else | |
6963 { | |
6964 // Rewrite (a[i] = value) to (a.opIndex(i, value)) | |
6965 if (search_function(ad, id)) | |
6966 { Expression *e = new DotIdExp(loc, ae->e1, id); | |
6967 | |
6968 if (1 || !global.params.useDeprecated) | |
6969 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); | |
6970 | |
6971 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2); | |
6972 e = e->semantic(sc); | |
6973 return e; | |
6974 } | |
6975 } | |
6976 } | |
6977 } | |
6978 /* Look for operator overloading of a[i..j]=value. | |
6979 * Do it before semantic() otherwise the a[i..j] will have been | |
6980 * converted to a.opSlice() already. | |
6981 */ | |
6982 if (e1->op == TOKslice) | |
6983 { Type *t1; | |
6984 SliceExp *ae = (SliceExp *)e1; | |
6985 AggregateDeclaration *ad; | |
6986 Identifier *id = Id::index; | |
6987 | |
6988 ae->e1 = ae->e1->semantic(sc); | |
6989 ae->e1 = resolveProperties(sc, ae->e1); | |
6990 t1 = ae->e1->type->toBasetype(); | |
6991 if (t1->ty == Tstruct) | |
6992 { | |
6993 ad = ((TypeStruct *)t1)->sym; | |
6994 goto L2; | |
6995 } | |
6996 else if (t1->ty == Tclass) | |
6997 { | |
6998 ad = ((TypeClass *)t1)->sym; | |
6999 L2: | |
7000 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j)) | |
7001 if (search_function(ad, Id::sliceass)) | |
7002 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass); | |
7003 Expressions *a = new Expressions(); | |
7004 | |
7005 a->push(e2); | |
7006 if (ae->lwr) | |
7007 { a->push(ae->lwr); | |
7008 assert(ae->upr); | |
7009 a->push(ae->upr); | |
7010 } | |
7011 else | |
7012 assert(!ae->upr); | |
7013 e = new CallExp(loc, e, a); | |
7014 e = e->semantic(sc); | |
7015 return e; | |
7016 } | |
7017 } | |
7018 } | |
7019 | |
7020 BinExp::semantic(sc); | |
7021 e2 = resolveProperties(sc, e2); | |
7022 assert(e1->type); | |
7023 | |
7024 /* Rewrite tuple assignment as a tuple of assignments. | |
7025 */ | |
7026 if (e1->op == TOKtuple && e2->op == TOKtuple) | |
7027 { TupleExp *tup1 = (TupleExp *)e1; | |
7028 TupleExp *tup2 = (TupleExp *)e2; | |
7029 size_t dim = tup1->exps->dim; | |
7030 if (dim != tup2->exps->dim) | |
7031 { | |
7032 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim); | |
7033 } | |
7034 else | |
7035 { Expressions *exps = new Expressions; | |
7036 exps->setDim(dim); | |
7037 | |
7038 for (int i = 0; i < dim; i++) | |
7039 { Expression *ex1 = (Expression *)tup1->exps->data[i]; | |
7040 Expression *ex2 = (Expression *)tup2->exps->data[i]; | |
7041 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2); | |
7042 } | |
7043 Expression *e = new TupleExp(loc, exps); | |
7044 e = e->semantic(sc); | |
7045 return e; | |
7046 } | |
7047 } | |
7048 | |
7049 t1 = e1->type->toBasetype(); | |
7050 | |
7051 if (t1->ty == Tfunction) | |
7052 { // Rewrite f=value to f(value) | |
7053 Expression *e; | |
7054 | |
7055 e = new CallExp(loc, e1, e2); | |
7056 e = e->semantic(sc); | |
7057 return e; | |
7058 } | |
7059 | |
7060 /* If it is an assignment from a 'foreign' type, | |
7061 * check for operator overloading. | |
7062 */ | |
7063 if (t1->ty == Tclass || t1->ty == Tstruct) | |
7064 { | |
7065 if (!e2->type->implicitConvTo(e1->type)) | |
7066 { | |
7067 Expression *e = op_overload(sc); | |
7068 if (e) | |
7069 return e; | |
7070 } | |
7071 } | |
7072 | |
7073 e2->rvalue(); | |
7074 | |
7075 if (e1->op == TOKarraylength) | |
7076 { | |
7077 // e1 is not an lvalue, but we let code generator handle it | |
7078 ArrayLengthExp *ale = (ArrayLengthExp *)e1; | |
7079 | |
7080 ale->e1 = ale->e1->modifiableLvalue(sc, e1); | |
7081 } | |
7082 else if (e1->op == TOKslice) | |
7083 ; | |
7084 else | |
7085 { // Try to do a decent error message with the expression | |
7086 // before it got constant folded | |
7087 e1 = e1->modifiableLvalue(sc, e1old); | |
7088 } | |
7089 | |
7090 if (e1->op == TOKslice && | |
7091 t1->nextOf() && | |
7092 e2->implicitConvTo(t1->nextOf()) | |
7093 // !(t1->nextOf()->equals(e2->type->nextOf())) | |
7094 ) | |
7095 { // memset | |
7096 ismemset = 1; // make it easy for back end to tell what this is | |
7097 e2 = e2->implicitCastTo(sc, t1->next); | |
7098 } | |
7099 else if (t1->ty == Tsarray) | |
7100 { | |
7101 error("cannot assign to static array %s", e1->toChars()); | |
7102 } | |
7103 else | |
7104 { | |
7105 e2 = e2->implicitCastTo(sc, e1->type); | |
7106 } | |
7107 type = e1->type; | |
7108 assert(type); | |
7109 return this; | |
7110 } | |
7111 | |
7112 Expression *AssignExp::checkToBoolean() | |
7113 { | |
7114 // Things like: | |
7115 // if (a = b) ... | |
7116 // are usually mistakes. | |
7117 | |
7118 error("'=' does not give a boolean result"); | |
7119 return this; | |
7120 } | |
7121 | |
7122 /************************************************************/ | |
7123 | |
7124 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7125 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) | |
7126 { | |
7127 } | |
7128 | |
7129 Expression *AddAssignExp::semantic(Scope *sc) | |
7130 { Expression *e; | |
7131 | |
7132 if (type) | |
7133 return this; | |
7134 | |
7135 BinExp::semantic(sc); | |
7136 e2 = resolveProperties(sc, e2); | |
7137 | |
7138 e = op_overload(sc); | |
7139 if (e) | |
7140 return e; | |
7141 | |
7142 e1 = e1->modifiableLvalue(sc, e1); | |
7143 | |
7144 Type *tb1 = e1->type->toBasetype(); | |
7145 Type *tb2 = e2->type->toBasetype(); | |
7146 | |
7147 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && | |
7148 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
7149 tb1->next->equals(tb2->next) | |
7150 ) | |
7151 { | |
7152 type = e1->type; | |
7153 e = this; | |
7154 } | |
7155 else | |
7156 { | |
7157 e1->checkScalar(); | |
7158 e1->checkNoBool(); | |
7159 if (tb1->ty == Tpointer && tb2->isintegral()) | |
7160 e = scaleFactor(sc); | |
7161 else if (tb1->ty == Tbit || tb1->ty == Tbool) | |
7162 { | |
7163 #if 0 | |
7164 // Need to rethink this | |
7165 if (e1->op != TOKvar) | |
7166 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 | |
7167 VarDeclaration *v; | |
7168 Expression *ea; | |
7169 Expression *ex; | |
7170 | |
7171 char name[6+6+1]; | |
7172 Identifier *id; | |
7173 static int idn; | |
7174 sprintf(name, "__name%d", ++idn); | |
7175 id = Lexer::idPool(name); | |
7176 | |
7177 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); | |
7178 v->semantic(sc); | |
7179 if (!sc->insert(v)) | |
7180 assert(0); | |
7181 v->parent = sc->func; | |
7182 | |
7183 ea = new AddrExp(loc, e1); | |
7184 ea = new AssignExp(loc, new VarExp(loc, v), ea); | |
7185 | |
7186 ex = new VarExp(loc, v); | |
7187 ex = new PtrExp(loc, ex); | |
7188 e = new AddExp(loc, ex, e2); | |
7189 e = new CastExp(loc, e, e1->type); | |
7190 e = new AssignExp(loc, ex->syntaxCopy(), e); | |
7191 | |
7192 e = new CommaExp(loc, ea, e); | |
7193 } | |
7194 else | |
7195 #endif | |
7196 { // Rewrite e1+=e2 to e1=e1+e2 | |
7197 // BUG: doesn't account for side effects in e1 | |
7198 // BUG: other assignment operators for bits aren't handled at all | |
7199 e = new AddExp(loc, e1, e2); | |
7200 e = new CastExp(loc, e, e1->type); | |
7201 e = new AssignExp(loc, e1->syntaxCopy(), e); | |
7202 } | |
7203 e = e->semantic(sc); | |
7204 } | |
7205 else | |
7206 { | |
7207 type = e1->type; | |
7208 typeCombine(sc); | |
7209 e1->checkArithmetic(); | |
7210 e2->checkArithmetic(); | |
7211 if (type->isreal() || type->isimaginary()) | |
7212 { | |
7213 assert(global.errors || e2->type->isfloating()); | |
7214 e2 = e2->castTo(sc, e1->type); | |
7215 } | |
7216 e = this; | |
7217 } | |
7218 } | |
7219 return e; | |
7220 } | |
7221 | |
7222 /************************************************************/ | |
7223 | |
7224 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7225 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) | |
7226 { | |
7227 } | |
7228 | |
7229 Expression *MinAssignExp::semantic(Scope *sc) | |
7230 { Expression *e; | |
7231 | |
7232 if (type) | |
7233 return this; | |
7234 | |
7235 BinExp::semantic(sc); | |
7236 e2 = resolveProperties(sc, e2); | |
7237 | |
7238 e = op_overload(sc); | |
7239 if (e) | |
7240 return e; | |
7241 | |
7242 e1 = e1->modifiableLvalue(sc, e1); | |
7243 e1->checkScalar(); | |
7244 e1->checkNoBool(); | |
7245 if (e1->type->ty == Tpointer && e2->type->isintegral()) | |
7246 e = scaleFactor(sc); | |
7247 else | |
7248 { | |
7249 e1 = e1->checkArithmetic(); | |
7250 e2 = e2->checkArithmetic(); | |
7251 type = e1->type; | |
7252 typeCombine(sc); | |
7253 if (type->isreal() || type->isimaginary()) | |
7254 { | |
7255 assert(e2->type->isfloating()); | |
7256 e2 = e2->castTo(sc, e1->type); | |
7257 } | |
7258 e = this; | |
7259 } | |
7260 return e; | |
7261 } | |
7262 | |
7263 /************************************************************/ | |
7264 | |
7265 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7266 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) | |
7267 { | |
7268 } | |
7269 | |
7270 Expression *CatAssignExp::semantic(Scope *sc) | |
7271 { Expression *e; | |
7272 | |
7273 BinExp::semantic(sc); | |
7274 e2 = resolveProperties(sc, e2); | |
7275 | |
7276 e = op_overload(sc); | |
7277 if (e) | |
7278 return e; | |
7279 | |
7280 if (e1->op == TOKslice) | |
7281 { SliceExp *se = (SliceExp *)e1; | |
7282 | |
7283 if (se->e1->type->toBasetype()->ty == Tsarray) | |
7284 error("cannot append to static array %s", se->e1->type->toChars()); | |
7285 } | |
7286 | |
7287 e1 = e1->modifiableLvalue(sc, e1); | |
7288 | |
7289 Type *tb1 = e1->type->toBasetype(); | |
7290 Type *tb2 = e2->type->toBasetype(); | |
7291 | |
7292 e2->rvalue(); | |
7293 | |
7294 if ((tb1->ty == Tarray) && | |
7295 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
7296 e2->implicitConvTo(e1->type) | |
7297 //e1->type->next->equals(e2->type->next) | |
7298 ) | |
7299 { // Append array | |
7300 e2 = e2->castTo(sc, e1->type); | |
7301 type = e1->type; | |
7302 e = this; | |
7303 } | |
7304 else if ((tb1->ty == Tarray) && | |
7305 e2->implicitConvTo(tb1->next) | |
7306 ) | |
7307 { // Append element | |
7308 e2 = e2->castTo(sc, tb1->next); | |
7309 type = e1->type; | |
7310 e = this; | |
7311 } | |
7312 else | |
7313 { | |
7314 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); | |
7315 type = Type::tint32; | |
7316 e = this; | |
7317 } | |
7318 return e; | |
7319 } | |
7320 | |
7321 /************************************************************/ | |
7322 | |
7323 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7324 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) | |
7325 { | |
7326 } | |
7327 | |
7328 Expression *MulAssignExp::semantic(Scope *sc) | |
7329 { Expression *e; | |
7330 | |
7331 BinExp::semantic(sc); | |
7332 e2 = resolveProperties(sc, e2); | |
7333 | |
7334 e = op_overload(sc); | |
7335 if (e) | |
7336 return e; | |
7337 | |
7338 e1 = e1->modifiableLvalue(sc, e1); | |
7339 e1->checkScalar(); | |
7340 e1->checkNoBool(); | |
7341 type = e1->type; | |
7342 typeCombine(sc); | |
7343 e1->checkArithmetic(); | |
7344 e2->checkArithmetic(); | |
7345 if (e2->type->isfloating()) | |
7346 { Type *t1; | |
7347 Type *t2; | |
7348 | |
7349 t1 = e1->type; | |
7350 t2 = e2->type; | |
7351 if (t1->isreal()) | |
7352 { | |
7353 if (t2->isimaginary() || t2->iscomplex()) | |
7354 { | |
7355 e2 = e2->castTo(sc, t1); | |
7356 } | |
7357 } | |
7358 else if (t1->isimaginary()) | |
7359 { | |
7360 if (t2->isimaginary() || t2->iscomplex()) | |
7361 { | |
7362 switch (t1->ty) | |
7363 { | |
7364 case Timaginary32: t2 = Type::tfloat32; break; | |
7365 case Timaginary64: t2 = Type::tfloat64; break; | |
7366 case Timaginary80: t2 = Type::tfloat80; break; | |
7367 default: | |
7368 assert(0); | |
7369 } | |
7370 e2 = e2->castTo(sc, t2); | |
7371 } | |
7372 } | |
7373 } | |
7374 return this; | |
7375 } | |
7376 | |
7377 /************************************************************/ | |
7378 | |
7379 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7380 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) | |
7381 { | |
7382 } | |
7383 | |
7384 Expression *DivAssignExp::semantic(Scope *sc) | |
7385 { Expression *e; | |
7386 | |
7387 BinExp::semantic(sc); | |
7388 e2 = resolveProperties(sc, e2); | |
7389 | |
7390 e = op_overload(sc); | |
7391 if (e) | |
7392 return e; | |
7393 | |
7394 e1 = e1->modifiableLvalue(sc, e1); | |
7395 e1->checkScalar(); | |
7396 e1->checkNoBool(); | |
7397 type = e1->type; | |
7398 typeCombine(sc); | |
7399 e1->checkArithmetic(); | |
7400 e2->checkArithmetic(); | |
7401 if (e2->type->isimaginary()) | |
7402 { Type *t1; | |
7403 Type *t2; | |
7404 | |
7405 t1 = e1->type; | |
7406 if (t1->isreal()) | |
7407 { // x/iv = i(-x/v) | |
7408 // Therefore, the result is 0 | |
7409 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); | |
7410 e2->type = t1; | |
7411 e = new AssignExp(loc, e1, e2); | |
7412 e->type = t1; | |
7413 return e; | |
7414 } | |
7415 else if (t1->isimaginary()) | |
7416 { Expression *e; | |
7417 | |
7418 switch (t1->ty) | |
7419 { | |
7420 case Timaginary32: t2 = Type::tfloat32; break; | |
7421 case Timaginary64: t2 = Type::tfloat64; break; | |
7422 case Timaginary80: t2 = Type::tfloat80; break; | |
7423 default: | |
7424 assert(0); | |
7425 } | |
7426 e2 = e2->castTo(sc, t2); | |
7427 e = new AssignExp(loc, e1, e2); | |
7428 e->type = t1; | |
7429 return e; | |
7430 } | |
7431 } | |
7432 return this; | |
7433 } | |
7434 | |
7435 /************************************************************/ | |
7436 | |
7437 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7438 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) | |
7439 { | |
7440 } | |
7441 | |
7442 Expression *ModAssignExp::semantic(Scope *sc) | |
7443 { | |
7444 return commonSemanticAssign(sc); | |
7445 } | |
7446 | |
7447 /************************************************************/ | |
7448 | |
7449 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7450 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) | |
7451 { | |
7452 } | |
7453 | |
7454 Expression *ShlAssignExp::semantic(Scope *sc) | |
7455 { Expression *e; | |
7456 | |
7457 //printf("ShlAssignExp::semantic()\n"); | |
7458 BinExp::semantic(sc); | |
7459 e2 = resolveProperties(sc, e2); | |
7460 | |
7461 e = op_overload(sc); | |
7462 if (e) | |
7463 return e; | |
7464 | |
7465 e1 = e1->modifiableLvalue(sc, e1); | |
7466 e1->checkScalar(); | |
7467 e1->checkNoBool(); | |
7468 type = e1->type; | |
7469 typeCombine(sc); | |
7470 e1->checkIntegral(); | |
7471 e2 = e2->checkIntegral(); | |
7472 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
7473 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
7474 return this; | |
7475 } | |
7476 | |
7477 /************************************************************/ | |
7478 | |
7479 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7480 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) | |
7481 { | |
7482 } | |
7483 | |
7484 Expression *ShrAssignExp::semantic(Scope *sc) | |
7485 { Expression *e; | |
7486 | |
7487 BinExp::semantic(sc); | |
7488 e2 = resolveProperties(sc, e2); | |
7489 | |
7490 e = op_overload(sc); | |
7491 if (e) | |
7492 return e; | |
7493 | |
7494 e1 = e1->modifiableLvalue(sc, e1); | |
7495 e1->checkScalar(); | |
7496 e1->checkNoBool(); | |
7497 type = e1->type; | |
7498 typeCombine(sc); | |
7499 e1->checkIntegral(); | |
7500 e2 = e2->checkIntegral(); | |
7501 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
7502 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
7503 return this; | |
7504 } | |
7505 | |
7506 /************************************************************/ | |
7507 | |
7508 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7509 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) | |
7510 { | |
7511 } | |
7512 | |
7513 Expression *UshrAssignExp::semantic(Scope *sc) | |
7514 { Expression *e; | |
7515 | |
7516 BinExp::semantic(sc); | |
7517 e2 = resolveProperties(sc, e2); | |
7518 | |
7519 e = op_overload(sc); | |
7520 if (e) | |
7521 return e; | |
7522 | |
7523 e1 = e1->modifiableLvalue(sc, e1); | |
7524 e1->checkScalar(); | |
7525 e1->checkNoBool(); | |
7526 type = e1->type; | |
7527 typeCombine(sc); | |
7528 e1->checkIntegral(); | |
7529 e2 = e2->checkIntegral(); | |
7530 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
7531 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
7532 return this; | |
7533 } | |
7534 | |
7535 /************************************************************/ | |
7536 | |
7537 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7538 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) | |
7539 { | |
7540 } | |
7541 | |
7542 Expression *AndAssignExp::semantic(Scope *sc) | |
7543 { | |
7544 return commonSemanticAssignIntegral(sc); | |
7545 } | |
7546 | |
7547 /************************************************************/ | |
7548 | |
7549 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7550 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) | |
7551 { | |
7552 } | |
7553 | |
7554 Expression *OrAssignExp::semantic(Scope *sc) | |
7555 { | |
7556 return commonSemanticAssignIntegral(sc); | |
7557 } | |
7558 | |
7559 /************************************************************/ | |
7560 | |
7561 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7562 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) | |
7563 { | |
7564 } | |
7565 | |
7566 Expression *XorAssignExp::semantic(Scope *sc) | |
7567 { | |
7568 return commonSemanticAssignIntegral(sc); | |
7569 } | |
7570 | |
7571 /************************* AddExp *****************************/ | |
7572 | |
7573 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2) | |
7574 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2) | |
7575 { | |
7576 llvmFieldIndex = false; | |
7577 } | |
7578 | |
7579 Expression *AddExp::semantic(Scope *sc) | |
7580 { Expression *e; | |
7581 | |
7582 #if LOGSEMANTIC | |
7583 printf("AddExp::semantic('%s')\n", toChars()); | |
7584 #endif | |
7585 if (!type) | |
7586 { | |
7587 BinExp::semanticp(sc); | |
7588 | |
7589 e = op_overload(sc); | |
7590 if (e) | |
7591 return e; | |
7592 | |
7593 Type *tb1 = e1->type->toBasetype(); | |
7594 Type *tb2 = e2->type->toBasetype(); | |
7595 | |
7596 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && | |
7597 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
7598 tb1->next->equals(tb2->next) | |
7599 ) | |
7600 { | |
7601 type = e1->type; | |
7602 e = this; | |
7603 } | |
7604 else if (tb1->ty == Tpointer && e2->type->isintegral() || | |
7605 tb2->ty == Tpointer && e1->type->isintegral()) | |
7606 e = scaleFactor(sc); | |
7607 else if (tb1->ty == Tpointer && tb2->ty == Tpointer) | |
7608 { | |
7609 incompatibleTypes(); | |
7610 type = e1->type; | |
7611 e = this; | |
7612 } | |
7613 else | |
7614 { | |
7615 typeCombine(sc); | |
7616 if ((e1->type->isreal() && e2->type->isimaginary()) || | |
7617 (e1->type->isimaginary() && e2->type->isreal())) | |
7618 { | |
7619 switch (type->toBasetype()->ty) | |
7620 { | |
7621 case Tfloat32: | |
7622 case Timaginary32: | |
7623 type = Type::tcomplex32; | |
7624 break; | |
7625 | |
7626 case Tfloat64: | |
7627 case Timaginary64: | |
7628 type = Type::tcomplex64; | |
7629 break; | |
7630 | |
7631 case Tfloat80: | |
7632 case Timaginary80: | |
7633 type = Type::tcomplex80; | |
7634 break; | |
7635 | |
7636 default: | |
7637 assert(0); | |
7638 } | |
7639 } | |
7640 e = this; | |
7641 } | |
7642 return e; | |
7643 } | |
7644 return this; | |
7645 } | |
7646 | |
7647 /************************************************************/ | |
7648 | |
7649 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2) | |
7650 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2) | |
7651 { | |
7652 } | |
7653 | |
7654 Expression *MinExp::semantic(Scope *sc) | |
7655 { Expression *e; | |
7656 Type *t1; | |
7657 Type *t2; | |
7658 | |
7659 #if LOGSEMANTIC | |
7660 printf("MinExp::semantic('%s')\n", toChars()); | |
7661 #endif | |
7662 if (type) | |
7663 return this; | |
7664 | |
7665 BinExp::semanticp(sc); | |
7666 | |
7667 e = op_overload(sc); | |
7668 if (e) | |
7669 return e; | |
7670 | |
7671 e = this; | |
7672 t1 = e1->type->toBasetype(); | |
7673 t2 = e2->type->toBasetype(); | |
7674 if (t1->ty == Tpointer) | |
7675 { | |
7676 if (t2->ty == Tpointer) | |
7677 { // Need to divide the result by the stride | |
7678 // Replace (ptr - ptr) with (ptr - ptr) / stride | |
7679 d_int64 stride; | |
7680 Expression *e; | |
7681 | |
7682 typeCombine(sc); // make sure pointer types are compatible | |
7683 type = Type::tptrdiff_t; | |
7684 stride = t2->next->size(); | |
7685 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); | |
7686 e->type = Type::tptrdiff_t; | |
7687 return e; | |
7688 } | |
7689 else if (t2->isintegral()) | |
7690 e = scaleFactor(sc); | |
7691 else | |
7692 { error("incompatible types for -"); | |
7693 return new IntegerExp(0); | |
7694 } | |
7695 } | |
7696 else if (t2->ty == Tpointer) | |
7697 { | |
7698 type = e2->type; | |
7699 error("can't subtract pointer from %s", e1->type->toChars()); | |
7700 return new IntegerExp(0); | |
7701 } | |
7702 else | |
7703 { | |
7704 typeCombine(sc); | |
7705 t1 = e1->type->toBasetype(); | |
7706 t2 = e2->type->toBasetype(); | |
7707 if ((t1->isreal() && t2->isimaginary()) || | |
7708 (t1->isimaginary() && t2->isreal())) | |
7709 { | |
7710 switch (type->ty) | |
7711 { | |
7712 case Tfloat32: | |
7713 case Timaginary32: | |
7714 type = Type::tcomplex32; | |
7715 break; | |
7716 | |
7717 case Tfloat64: | |
7718 case Timaginary64: | |
7719 type = Type::tcomplex64; | |
7720 break; | |
7721 | |
7722 case Tfloat80: | |
7723 case Timaginary80: | |
7724 type = Type::tcomplex80; | |
7725 break; | |
7726 | |
7727 default: | |
7728 assert(0); | |
7729 } | |
7730 } | |
7731 } | |
7732 return e; | |
7733 } | |
7734 | |
7735 /************************* CatExp *****************************/ | |
7736 | |
7737 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2) | |
7738 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2) | |
7739 { | |
7740 } | |
7741 | |
7742 Expression *CatExp::semantic(Scope *sc) | |
7743 { Expression *e; | |
7744 | |
7745 //printf("CatExp::semantic() %s\n", toChars()); | |
7746 if (!type) | |
7747 { | |
7748 BinExp::semanticp(sc); | |
7749 e = op_overload(sc); | |
7750 if (e) | |
7751 return e; | |
7752 | |
7753 Type *tb1 = e1->type->toBasetype(); | |
7754 Type *tb2 = e2->type->toBasetype(); | |
7755 | |
7756 | |
7757 /* BUG: Should handle things like: | |
7758 * char c; | |
7759 * c ~ ' ' | |
7760 * ' ' ~ c; | |
7761 */ | |
7762 | |
7763 #if 0 | |
7764 e1->type->print(); | |
7765 e2->type->print(); | |
7766 #endif | |
7767 if ((tb1->ty == Tsarray || tb1->ty == Tarray) && | |
7768 e2->type->equals(tb1->next)) | |
7769 { | |
7770 type = tb1->next->arrayOf(); | |
7771 if (tb2->ty == Tarray) | |
7772 { // Make e2 into [e2] | |
7773 e2 = new ArrayLiteralExp(e2->loc, e2); | |
7774 e2->type = type; | |
7775 } | |
7776 return this; | |
7777 } | |
7778 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && | |
7779 e1->type->equals(tb2->next)) | |
7780 { | |
7781 type = tb2->next->arrayOf(); | |
7782 if (tb1->ty == Tarray) | |
7783 { // Make e1 into [e1] | |
7784 e1 = new ArrayLiteralExp(e1->loc, e1); | |
7785 e1->type = type; | |
7786 } | |
7787 return this; | |
7788 } | |
7789 | |
7790 typeCombine(sc); | |
7791 | |
7792 if (type->toBasetype()->ty == Tsarray) | |
7793 type = type->toBasetype()->next->arrayOf(); | |
7794 #if 0 | |
7795 e1->type->print(); | |
7796 e2->type->print(); | |
7797 type->print(); | |
7798 print(); | |
7799 #endif | |
7800 if (e1->op == TOKstring && e2->op == TOKstring) | |
7801 e = optimize(WANTvalue); | |
7802 else if (e1->type->equals(e2->type) && | |
7803 (e1->type->toBasetype()->ty == Tarray || | |
7804 e1->type->toBasetype()->ty == Tsarray)) | |
7805 { | |
7806 e = this; | |
7807 } | |
7808 else | |
7809 { | |
7810 error("Can only concatenate arrays, not (%s ~ %s)", | |
7811 e1->type->toChars(), e2->type->toChars()); | |
7812 type = Type::tint32; | |
7813 e = this; | |
7814 } | |
7815 e->type = e->type->semantic(loc, sc); | |
7816 return e; | |
7817 } | |
7818 return this; | |
7819 } | |
7820 | |
7821 /************************************************************/ | |
7822 | |
7823 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2) | |
7824 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2) | |
7825 { | |
7826 } | |
7827 | |
7828 Expression *MulExp::semantic(Scope *sc) | |
7829 { Expression *e; | |
7830 | |
7831 #if 0 | |
7832 printf("MulExp::semantic() %s\n", toChars()); | |
7833 #endif | |
7834 if (type) | |
7835 { | |
7836 return this; | |
7837 } | |
7838 | |
7839 BinExp::semanticp(sc); | |
7840 e = op_overload(sc); | |
7841 if (e) | |
7842 return e; | |
7843 | |
7844 typeCombine(sc); | |
7845 e1->checkArithmetic(); | |
7846 e2->checkArithmetic(); | |
7847 if (type->isfloating()) | |
7848 { Type *t1 = e1->type; | |
7849 Type *t2 = e2->type; | |
7850 | |
7851 if (t1->isreal()) | |
7852 { | |
7853 type = t2; | |
7854 } | |
7855 else if (t2->isreal()) | |
7856 { | |
7857 type = t1; | |
7858 } | |
7859 else if (t1->isimaginary()) | |
7860 { | |
7861 if (t2->isimaginary()) | |
7862 { Expression *e; | |
7863 | |
7864 switch (t1->ty) | |
7865 { | |
7866 case Timaginary32: type = Type::tfloat32; break; | |
7867 case Timaginary64: type = Type::tfloat64; break; | |
7868 case Timaginary80: type = Type::tfloat80; break; | |
7869 default: assert(0); | |
7870 } | |
7871 | |
7872 // iy * iv = -yv | |
7873 e1->type = type; | |
7874 e2->type = type; | |
7875 e = new NegExp(loc, this); | |
7876 e = e->semantic(sc); | |
7877 return e; | |
7878 } | |
7879 else | |
7880 type = t2; // t2 is complex | |
7881 } | |
7882 else if (t2->isimaginary()) | |
7883 { | |
7884 type = t1; // t1 is complex | |
7885 } | |
7886 } | |
7887 return this; | |
7888 } | |
7889 | |
7890 /************************************************************/ | |
7891 | |
7892 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2) | |
7893 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2) | |
7894 { | |
7895 } | |
7896 | |
7897 Expression *DivExp::semantic(Scope *sc) | |
7898 { Expression *e; | |
7899 | |
7900 if (type) | |
7901 return this; | |
7902 | |
7903 BinExp::semanticp(sc); | |
7904 e = op_overload(sc); | |
7905 if (e) | |
7906 return e; | |
7907 | |
7908 typeCombine(sc); | |
7909 e1->checkArithmetic(); | |
7910 e2->checkArithmetic(); | |
7911 if (type->isfloating()) | |
7912 { Type *t1 = e1->type; | |
7913 Type *t2 = e2->type; | |
7914 | |
7915 if (t1->isreal()) | |
7916 { | |
7917 type = t2; | |
7918 if (t2->isimaginary()) | |
7919 { Expression *e; | |
7920 | |
7921 // x/iv = i(-x/v) | |
7922 e2->type = t1; | |
7923 e = new NegExp(loc, this); | |
7924 e = e->semantic(sc); | |
7925 return e; | |
7926 } | |
7927 } | |
7928 else if (t2->isreal()) | |
7929 { | |
7930 type = t1; | |
7931 } | |
7932 else if (t1->isimaginary()) | |
7933 { | |
7934 if (t2->isimaginary()) | |
7935 { | |
7936 switch (t1->ty) | |
7937 { | |
7938 case Timaginary32: type = Type::tfloat32; break; | |
7939 case Timaginary64: type = Type::tfloat64; break; | |
7940 case Timaginary80: type = Type::tfloat80; break; | |
7941 default: assert(0); | |
7942 } | |
7943 } | |
7944 else | |
7945 type = t2; // t2 is complex | |
7946 } | |
7947 else if (t2->isimaginary()) | |
7948 { | |
7949 type = t1; // t1 is complex | |
7950 } | |
7951 } | |
7952 return this; | |
7953 } | |
7954 | |
7955 /************************************************************/ | |
7956 | |
7957 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2) | |
7958 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2) | |
7959 { | |
7960 } | |
7961 | |
7962 Expression *ModExp::semantic(Scope *sc) | |
7963 { Expression *e; | |
7964 | |
7965 if (type) | |
7966 return this; | |
7967 | |
7968 BinExp::semanticp(sc); | |
7969 e = op_overload(sc); | |
7970 if (e) | |
7971 return e; | |
7972 | |
7973 typeCombine(sc); | |
7974 e1->checkArithmetic(); | |
7975 e2->checkArithmetic(); | |
7976 if (type->isfloating()) | |
7977 { type = e1->type; | |
7978 if (e2->type->iscomplex()) | |
7979 { error("cannot perform modulo complex arithmetic"); | |
7980 return new IntegerExp(0); | |
7981 } | |
7982 } | |
7983 return this; | |
7984 } | |
7985 | |
7986 /************************************************************/ | |
7987 | |
7988 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2) | |
7989 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2) | |
7990 { | |
7991 } | |
7992 | |
7993 Expression *ShlExp::semantic(Scope *sc) | |
7994 { Expression *e; | |
7995 | |
7996 //printf("ShlExp::semantic(), type = %p\n", type); | |
7997 if (!type) | |
7998 { BinExp::semanticp(sc); | |
7999 e = op_overload(sc); | |
8000 if (e) | |
8001 return e; | |
8002 e1 = e1->checkIntegral(); | |
8003 e2 = e2->checkIntegral(); | |
8004 e1 = e1->integralPromotions(sc); | |
8005 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
8006 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
8007 type = e1->type; | |
8008 } | |
8009 return this; | |
8010 } | |
8011 | |
8012 /************************************************************/ | |
8013 | |
8014 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2) | |
8015 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2) | |
8016 { | |
8017 } | |
8018 | |
8019 Expression *ShrExp::semantic(Scope *sc) | |
8020 { Expression *e; | |
8021 | |
8022 if (!type) | |
8023 { BinExp::semanticp(sc); | |
8024 e = op_overload(sc); | |
8025 if (e) | |
8026 return e; | |
8027 e1 = e1->checkIntegral(); | |
8028 e2 = e2->checkIntegral(); | |
8029 e1 = e1->integralPromotions(sc); | |
8030 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
8031 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
8032 type = e1->type; | |
8033 } | |
8034 return this; | |
8035 } | |
8036 | |
8037 /************************************************************/ | |
8038 | |
8039 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2) | |
8040 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2) | |
8041 { | |
8042 } | |
8043 | |
8044 Expression *UshrExp::semantic(Scope *sc) | |
8045 { Expression *e; | |
8046 | |
8047 if (!type) | |
8048 { BinExp::semanticp(sc); | |
8049 e = op_overload(sc); | |
8050 if (e) | |
8051 return e; | |
8052 e1 = e1->checkIntegral(); | |
8053 e2 = e2->checkIntegral(); | |
8054 e1 = e1->integralPromotions(sc); | |
8055 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
8056 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
8057 type = e1->type; | |
8058 } | |
8059 return this; | |
8060 } | |
8061 | |
8062 /************************************************************/ | |
8063 | |
8064 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2) | |
8065 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2) | |
8066 { | |
8067 } | |
8068 | |
8069 Expression *AndExp::semantic(Scope *sc) | |
8070 { Expression *e; | |
8071 | |
8072 if (!type) | |
8073 { BinExp::semanticp(sc); | |
8074 e = op_overload(sc); | |
8075 if (e) | |
8076 return e; | |
8077 if (e1->type->toBasetype()->ty == Tbool && | |
8078 e2->type->toBasetype()->ty == Tbool) | |
8079 { | |
8080 type = e1->type; | |
8081 e = this; | |
8082 } | |
8083 else | |
8084 { | |
8085 typeCombine(sc); | |
8086 e1->checkIntegral(); | |
8087 e2->checkIntegral(); | |
8088 } | |
8089 } | |
8090 return this; | |
8091 } | |
8092 | |
8093 /************************************************************/ | |
8094 | |
8095 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2) | |
8096 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2) | |
8097 { | |
8098 } | |
8099 | |
8100 Expression *OrExp::semantic(Scope *sc) | |
8101 { Expression *e; | |
8102 | |
8103 if (!type) | |
8104 { BinExp::semanticp(sc); | |
8105 e = op_overload(sc); | |
8106 if (e) | |
8107 return e; | |
8108 if (e1->type->toBasetype()->ty == Tbool && | |
8109 e2->type->toBasetype()->ty == Tbool) | |
8110 { | |
8111 type = e1->type; | |
8112 e = this; | |
8113 } | |
8114 else | |
8115 { | |
8116 typeCombine(sc); | |
8117 e1->checkIntegral(); | |
8118 e2->checkIntegral(); | |
8119 } | |
8120 } | |
8121 return this; | |
8122 } | |
8123 | |
8124 /************************************************************/ | |
8125 | |
8126 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2) | |
8127 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2) | |
8128 { | |
8129 } | |
8130 | |
8131 Expression *XorExp::semantic(Scope *sc) | |
8132 { Expression *e; | |
8133 | |
8134 if (!type) | |
8135 { BinExp::semanticp(sc); | |
8136 e = op_overload(sc); | |
8137 if (e) | |
8138 return e; | |
8139 if (e1->type->toBasetype()->ty == Tbool && | |
8140 e2->type->toBasetype()->ty == Tbool) | |
8141 { | |
8142 type = e1->type; | |
8143 e = this; | |
8144 } | |
8145 else | |
8146 { | |
8147 typeCombine(sc); | |
8148 e1->checkIntegral(); | |
8149 e2->checkIntegral(); | |
8150 } | |
8151 } | |
8152 return this; | |
8153 } | |
8154 | |
8155 | |
8156 /************************************************************/ | |
8157 | |
8158 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2) | |
8159 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2) | |
8160 { | |
8161 } | |
8162 | |
8163 Expression *OrOrExp::semantic(Scope *sc) | |
8164 { | |
8165 unsigned cs1; | |
8166 | |
8167 // same as for AndAnd | |
8168 e1 = e1->semantic(sc); | |
8169 e1 = resolveProperties(sc, e1); | |
8170 e1 = e1->checkToPointer(); | |
8171 e1 = e1->checkToBoolean(); | |
8172 cs1 = sc->callSuper; | |
8173 | |
8174 if (sc->flags & SCOPEstaticif) | |
8175 { | |
8176 /* If in static if, don't evaluate e2 if we don't have to. | |
8177 */ | |
8178 e1 = e1->optimize(WANTflags); | |
8179 if (e1->isBool(TRUE)) | |
8180 { | |
8181 return new IntegerExp(loc, 1, Type::tboolean); | |
8182 } | |
8183 } | |
8184 | |
8185 e2 = e2->semantic(sc); | |
8186 sc->mergeCallSuper(loc, cs1); | |
8187 e2 = resolveProperties(sc, e2); | |
8188 e2 = e2->checkToPointer(); | |
8189 | |
8190 type = Type::tboolean; | |
8191 if (e1->type->ty == Tvoid) | |
8192 type = Type::tvoid; | |
8193 if (e2->op == TOKtype || e2->op == TOKimport) | |
8194 error("%s is not an expression", e2->toChars()); | |
8195 return this; | |
8196 } | |
8197 | |
8198 Expression *OrOrExp::checkToBoolean() | |
8199 { | |
8200 e2 = e2->checkToBoolean(); | |
8201 return this; | |
8202 } | |
8203 | |
8204 int OrOrExp::isBit() | |
8205 { | |
8206 return TRUE; | |
8207 } | |
8208 | |
8209 int OrOrExp::checkSideEffect(int flag) | |
8210 { | |
8211 if (flag == 2) | |
8212 { | |
8213 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
8214 } | |
8215 else | |
8216 { e1->checkSideEffect(1); | |
8217 return e2->checkSideEffect(flag); | |
8218 } | |
8219 } | |
8220 | |
8221 /************************************************************/ | |
8222 | |
8223 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2) | |
8224 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2) | |
8225 { | |
8226 } | |
8227 | |
8228 Expression *AndAndExp::semantic(Scope *sc) | |
8229 { | |
8230 unsigned cs1; | |
8231 | |
8232 // same as for OrOr | |
8233 e1 = e1->semantic(sc); | |
8234 e1 = resolveProperties(sc, e1); | |
8235 e1 = e1->checkToPointer(); | |
8236 e1 = e1->checkToBoolean(); | |
8237 cs1 = sc->callSuper; | |
8238 | |
8239 if (sc->flags & SCOPEstaticif) | |
8240 { | |
8241 /* If in static if, don't evaluate e2 if we don't have to. | |
8242 */ | |
8243 e1 = e1->optimize(WANTflags); | |
8244 if (e1->isBool(FALSE)) | |
8245 { | |
8246 return new IntegerExp(loc, 0, Type::tboolean); | |
8247 } | |
8248 } | |
8249 | |
8250 e2 = e2->semantic(sc); | |
8251 sc->mergeCallSuper(loc, cs1); | |
8252 e2 = resolveProperties(sc, e2); | |
8253 e2 = e2->checkToPointer(); | |
8254 | |
8255 type = Type::tboolean; | |
8256 if (e1->type->ty == Tvoid) | |
8257 type = Type::tvoid; | |
8258 if (e2->op == TOKtype || e2->op == TOKimport) | |
8259 error("%s is not an expression", e2->toChars()); | |
8260 return this; | |
8261 } | |
8262 | |
8263 Expression *AndAndExp::checkToBoolean() | |
8264 { | |
8265 e2 = e2->checkToBoolean(); | |
8266 return this; | |
8267 } | |
8268 | |
8269 int AndAndExp::isBit() | |
8270 { | |
8271 return TRUE; | |
8272 } | |
8273 | |
8274 int AndAndExp::checkSideEffect(int flag) | |
8275 { | |
8276 if (flag == 2) | |
8277 { | |
8278 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
8279 } | |
8280 else | |
8281 { | |
8282 e1->checkSideEffect(1); | |
8283 return e2->checkSideEffect(flag); | |
8284 } | |
8285 } | |
8286 | |
8287 /************************************************************/ | |
8288 | |
8289 InExp::InExp(Loc loc, Expression *e1, Expression *e2) | |
8290 : BinExp(loc, TOKin, sizeof(InExp), e1, e2) | |
8291 { | |
8292 } | |
8293 | |
8294 Expression *InExp::semantic(Scope *sc) | |
8295 { Expression *e; | |
8296 | |
8297 if (type) | |
8298 return this; | |
8299 | |
8300 BinExp::semanticp(sc); | |
8301 e = op_overload(sc); | |
8302 if (e) | |
8303 return e; | |
8304 | |
8305 //type = Type::tboolean; | |
8306 Type *t2b = e2->type->toBasetype(); | |
8307 if (t2b->ty != Taarray) | |
8308 { | |
8309 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); | |
8310 type = Type::terror; | |
8311 } | |
8312 else | |
8313 { | |
8314 TypeAArray *ta = (TypeAArray *)t2b; | |
8315 | |
8316 // Convert key to type of key | |
8317 e1 = e1->implicitCastTo(sc, ta->index); | |
8318 | |
8319 // Return type is pointer to value | |
8320 type = ta->next->pointerTo(); | |
8321 } | |
8322 return this; | |
8323 } | |
8324 | |
8325 int InExp::isBit() | |
8326 { | |
8327 return FALSE; | |
8328 } | |
8329 | |
8330 | |
8331 /************************************************************/ | |
8332 | |
8333 /* This deletes the key e1 from the associative array e2 | |
8334 */ | |
8335 | |
8336 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) | |
8337 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) | |
8338 { | |
8339 type = Type::tvoid; | |
8340 } | |
8341 | |
8342 /************************************************************/ | |
8343 | |
8344 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8345 : BinExp(loc, op, sizeof(CmpExp), e1, e2) | |
8346 { | |
8347 } | |
8348 | |
8349 Expression *CmpExp::semantic(Scope *sc) | |
8350 { Expression *e; | |
8351 Type *t1; | |
8352 Type *t2; | |
8353 | |
8354 #if LOGSEMANTIC | |
8355 printf("CmpExp::semantic('%s')\n", toChars()); | |
8356 #endif | |
8357 if (type) | |
8358 return this; | |
8359 | |
8360 BinExp::semanticp(sc); | |
8361 | |
8362 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
8363 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
8364 { | |
8365 error("do not use null when comparing class types"); | |
8366 } | |
8367 | |
8368 e = op_overload(sc); | |
8369 if (e) | |
8370 { | |
8371 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32)); | |
8372 e = e->semantic(sc); | |
8373 return e; | |
8374 } | |
8375 | |
8376 typeCombine(sc); | |
8377 type = Type::tboolean; | |
8378 | |
8379 // Special handling for array comparisons | |
8380 t1 = e1->type->toBasetype(); | |
8381 t2 = e2->type->toBasetype(); | |
8382 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
8383 (t2->ty == Tarray || t2->ty == Tsarray)) | |
8384 { | |
8385 if (!t1->next->equals(t2->next)) | |
8386 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
8387 e = this; | |
8388 } | |
8389 else if (t1->ty == Tstruct || t2->ty == Tstruct || | |
8390 (t1->ty == Tclass && t2->ty == Tclass)) | |
8391 { | |
8392 if (t2->ty == Tstruct) | |
8393 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars()); | |
8394 else | |
8395 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars()); | |
8396 e = this; | |
8397 } | |
8398 #if 1 | |
8399 else if (t1->iscomplex() || t2->iscomplex()) | |
8400 { | |
8401 error("compare not defined for complex operands"); | |
8402 e = new IntegerExp(0); | |
8403 } | |
8404 #endif | |
8405 else | |
8406 e = this; | |
8407 return e; | |
8408 } | |
8409 | |
8410 int CmpExp::isBit() | |
8411 { | |
8412 return TRUE; | |
8413 } | |
8414 | |
8415 | |
8416 /************************************************************/ | |
8417 | |
8418 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8419 : BinExp(loc, op, sizeof(EqualExp), e1, e2) | |
8420 { | |
8421 assert(op == TOKequal || op == TOKnotequal); | |
8422 } | |
8423 | |
8424 Expression *EqualExp::semantic(Scope *sc) | |
8425 { Expression *e; | |
8426 Type *t1; | |
8427 Type *t2; | |
8428 | |
8429 //printf("EqualExp::semantic('%s')\n", toChars()); | |
8430 if (type) | |
8431 return this; | |
8432 | |
8433 BinExp::semanticp(sc); | |
8434 | |
8435 /* Before checking for operator overloading, check to see if we're | |
8436 * comparing the addresses of two statics. If so, we can just see | |
8437 * if they are the same symbol. | |
8438 */ | |
8439 if (e1->op == TOKaddress && e2->op == TOKaddress) | |
8440 { AddrExp *ae1 = (AddrExp *)e1; | |
8441 AddrExp *ae2 = (AddrExp *)e2; | |
8442 | |
8443 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar) | |
8444 { VarExp *ve1 = (VarExp *)ae1->e1; | |
8445 VarExp *ve2 = (VarExp *)ae2->e1; | |
8446 | |
8447 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/) | |
8448 { | |
8449 // They are the same, result is 'true' for ==, 'false' for != | |
8450 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean); | |
8451 return e; | |
8452 } | |
8453 } | |
8454 } | |
8455 | |
8456 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
8457 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
8458 { | |
8459 error("use '%s' instead of '%s' when comparing with null", | |
8460 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity), | |
8461 Token::toChars(op)); | |
8462 } | |
8463 | |
8464 //if (e2->op != TOKnull) | |
8465 { | |
8466 e = op_overload(sc); | |
8467 if (e) | |
8468 { | |
8469 if (op == TOKnotequal) | |
8470 { | |
8471 e = new NotExp(e->loc, e); | |
8472 e = e->semantic(sc); | |
8473 } | |
8474 return e; | |
8475 } | |
8476 } | |
8477 | |
8478 e = typeCombine(sc); | |
8479 type = Type::tboolean; | |
8480 | |
8481 // Special handling for array comparisons | |
8482 t1 = e1->type->toBasetype(); | |
8483 t2 = e2->type->toBasetype(); | |
8484 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
8485 (t2->ty == Tarray || t2->ty == Tsarray)) | |
8486 { | |
8487 if (!t1->next->equals(t2->next)) | |
8488 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
8489 } | |
8490 else | |
8491 { | |
8492 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
8493 { | |
8494 // Cast both to complex | |
8495 e1 = e1->castTo(sc, Type::tcomplex80); | |
8496 e2 = e2->castTo(sc, Type::tcomplex80); | |
8497 } | |
8498 } | |
8499 return e; | |
8500 } | |
8501 | |
8502 int EqualExp::isBit() | |
8503 { | |
8504 return TRUE; | |
8505 } | |
8506 | |
8507 | |
8508 | |
8509 /************************************************************/ | |
8510 | |
8511 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8512 : BinExp(loc, op, sizeof(IdentityExp), e1, e2) | |
8513 { | |
8514 } | |
8515 | |
8516 Expression *IdentityExp::semantic(Scope *sc) | |
8517 { | |
8518 if (type) | |
8519 return this; | |
8520 | |
8521 BinExp::semanticp(sc); | |
8522 type = Type::tboolean; | |
8523 typeCombine(sc); | |
8524 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
8525 { | |
8526 // Cast both to complex | |
8527 e1 = e1->castTo(sc, Type::tcomplex80); | |
8528 e2 = e2->castTo(sc, Type::tcomplex80); | |
8529 } | |
8530 return this; | |
8531 } | |
8532 | |
8533 int IdentityExp::isBit() | |
8534 { | |
8535 return TRUE; | |
8536 } | |
8537 | |
8538 | |
8539 /****************************************************************/ | |
8540 | |
8541 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2) | |
8542 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2) | |
8543 { | |
8544 this->econd = econd; | |
8545 } | |
8546 | |
8547 Expression *CondExp::syntaxCopy() | |
8548 { | |
8549 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy()); | |
8550 } | |
8551 | |
8552 | |
8553 Expression *CondExp::semantic(Scope *sc) | |
8554 { Type *t1; | |
8555 Type *t2; | |
8556 unsigned cs0; | |
8557 unsigned cs1; | |
8558 | |
8559 #if LOGSEMANTIC | |
8560 printf("CondExp::semantic('%s')\n", toChars()); | |
8561 #endif | |
8562 if (type) | |
8563 return this; | |
8564 | |
8565 econd = econd->semantic(sc); | |
8566 econd = resolveProperties(sc, econd); | |
8567 econd = econd->checkToPointer(); | |
8568 econd = econd->checkToBoolean(); | |
8569 | |
8570 #if 0 /* this cannot work right because the types of e1 and e2 | |
8571 * both contribute to the type of the result. | |
8572 */ | |
8573 if (sc->flags & SCOPEstaticif) | |
8574 { | |
8575 /* If in static if, don't evaluate what we don't have to. | |
8576 */ | |
8577 econd = econd->optimize(WANTflags); | |
8578 if (econd->isBool(TRUE)) | |
8579 { | |
8580 e1 = e1->semantic(sc); | |
8581 e1 = resolveProperties(sc, e1); | |
8582 return e1; | |
8583 } | |
8584 else if (econd->isBool(FALSE)) | |
8585 { | |
8586 e2 = e2->semantic(sc); | |
8587 e2 = resolveProperties(sc, e2); | |
8588 return e2; | |
8589 } | |
8590 } | |
8591 #endif | |
8592 | |
8593 | |
8594 cs0 = sc->callSuper; | |
8595 e1 = e1->semantic(sc); | |
8596 e1 = resolveProperties(sc, e1); | |
8597 cs1 = sc->callSuper; | |
8598 sc->callSuper = cs0; | |
8599 e2 = e2->semantic(sc); | |
8600 e2 = resolveProperties(sc, e2); | |
8601 sc->mergeCallSuper(loc, cs1); | |
8602 | |
8603 | |
8604 // If either operand is void, the result is void | |
8605 t1 = e1->type; | |
8606 t2 = e2->type; | |
8607 if (t1->ty == Tvoid || t2->ty == Tvoid) | |
8608 type = Type::tvoid; | |
8609 else if (t1 == t2) | |
8610 type = t1; | |
8611 else | |
8612 { | |
8613 typeCombine(sc); | |
8614 switch (e1->type->toBasetype()->ty) | |
8615 { | |
8616 case Tcomplex32: | |
8617 case Tcomplex64: | |
8618 case Tcomplex80: | |
8619 e2 = e2->castTo(sc, e1->type); | |
8620 break; | |
8621 } | |
8622 switch (e2->type->toBasetype()->ty) | |
8623 { | |
8624 case Tcomplex32: | |
8625 case Tcomplex64: | |
8626 case Tcomplex80: | |
8627 e1 = e1->castTo(sc, e2->type); | |
8628 break; | |
8629 } | |
8630 } | |
8631 return this; | |
8632 } | |
8633 | |
8634 Expression *CondExp::toLvalue(Scope *sc, Expression *ex) | |
8635 { | |
8636 PtrExp *e; | |
8637 | |
8638 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) | |
8639 e = new PtrExp(loc, this, type); | |
8640 | |
8641 e1 = e1->addressOf(sc); | |
8642 //e1 = e1->toLvalue(sc, NULL); | |
8643 | |
8644 e2 = e2->addressOf(sc); | |
8645 //e2 = e2->toLvalue(sc, NULL); | |
8646 | |
8647 typeCombine(sc); | |
8648 | |
8649 type = e2->type; | |
8650 return e; | |
8651 } | |
8652 | |
8653 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e) | |
8654 { | |
8655 error("conditional expression %s is not a modifiable lvalue", toChars()); | |
8656 return this; | |
8657 } | |
8658 | |
8659 void CondExp::checkEscape() | |
8660 { | |
8661 e1->checkEscape(); | |
8662 e2->checkEscape(); | |
8663 } | |
8664 | |
8665 | |
8666 Expression *CondExp::checkToBoolean() | |
8667 { | |
8668 e1 = e1->checkToBoolean(); | |
8669 e2 = e2->checkToBoolean(); | |
8670 return this; | |
8671 } | |
8672 | |
8673 int CondExp::checkSideEffect(int flag) | |
8674 { | |
8675 if (flag == 2) | |
8676 { | |
8677 return econd->checkSideEffect(2) || | |
8678 e1->checkSideEffect(2) || | |
8679 e2->checkSideEffect(2); | |
8680 } | |
8681 else | |
8682 { | |
8683 econd->checkSideEffect(1); | |
8684 e1->checkSideEffect(flag); | |
8685 return e2->checkSideEffect(flag); | |
8686 } | |
8687 } | |
8688 | |
8689 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
8690 { | |
8691 expToCBuffer(buf, hgs, econd, PREC_oror); | |
8692 buf->writestring(" ? "); | |
8693 expToCBuffer(buf, hgs, e1, PREC_expr); | |
8694 buf->writestring(" : "); | |
8695 expToCBuffer(buf, hgs, e2, PREC_cond); | |
8696 } | |
8697 | |
8698 |