Mercurial > projects > ddmd
annotate dmd/VarDeclaration.d @ 98:5c859d5fbe27
and more
author | Trass3r |
---|---|
date | Tue, 31 Aug 2010 03:53:49 +0200 |
parents | 23280d154c5b |
children | e6090d1aea7c |
rev | line source |
---|---|
0 | 1 module dmd.VarDeclaration; |
2 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
3 import dmd.Array; |
0 | 4 import dmd.Declaration; |
5 import dmd.SliceExp; | |
6 import dmd.ClassDeclaration; | |
7 import dmd.DeleteExp; | |
8 import dmd.SymOffExp; | |
9 import dmd.DotIdExp; | |
10 import dmd.PtrExp; | |
11 import dmd.CallExp; | |
12 import dmd.DotVarExp; | |
13 import dmd.CommaExp; | |
14 import dmd.CastExp; | |
15 import dmd.WANT; | |
16 import dmd.StructDeclaration; | |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
17 import dmd.StorageClassDeclaration; |
0 | 18 import dmd.DsymbolExp; |
19 import dmd.TypeSArray; | |
20 import dmd.IntegerExp; | |
21 import dmd.VarExp; | |
22 import dmd.AssignExp; | |
23 import dmd.TypeTypedef; | |
24 import dmd.ArrayInitializer; | |
25 import dmd.StructInitializer; | |
26 import dmd.NewExp; | |
27 import dmd.TupleDeclaration; | |
28 import dmd.AggregateDeclaration; | |
29 import dmd.InterfaceDeclaration; | |
30 import dmd.TemplateInstance; | |
31 import dmd.Id; | |
32 import dmd.Initializer; | |
33 import dmd.TypeStruct; | |
34 import dmd.TypeTuple; | |
35 import dmd.Argument; | |
36 import dmd.ExpInitializer; | |
37 import dmd.ArrayTypes; | |
38 import dmd.Dsymbol; | |
39 import dmd.Expression; | |
40 import dmd.Loc; | |
41 import dmd.STC; | |
42 import dmd.TOK; | |
43 import dmd.TupleExp; | |
44 import dmd.Global; | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
45 import dmd.Module; |
0 | 46 import dmd.FuncDeclaration; |
47 import dmd.Type; | |
48 import dmd.TY; | |
49 import dmd.LINK; | |
50 import dmd.Scope; | |
51 import dmd.Identifier; | |
52 import dmd.OutBuffer; | |
53 import dmd.HdrGenState; | |
54 import dmd.PROT; | |
73 | 55 import dmd.expression.Util; |
0 | 56 |
57 import dmd.backend.Symbol; | |
58 import dmd.backend.TYM; | |
59 import dmd.backend.FL; | |
60 import dmd.backend.DT; | |
61 import dmd.backend.mTY; | |
62 import dmd.backend.SC; | |
63 import dmd.backend.mTYman; | |
64 import dmd.backend.TYPE; | |
65 import dmd.backend.Util; | |
66 import dmd.backend.LIST; | |
67 | |
68 import std.stdio : writef; | |
69 import std.string : toStringz; | |
70 | |
71 class VarDeclaration : Declaration | |
72 { | |
73 Initializer init; | |
74 uint offset; | |
75 bool noauto; // no auto semantics | |
76 version (DMDV2) { | |
98 | 77 FuncDeclarations nestedrefs; // referenced by these lexically nested functions |
78 bool isargptr = false; // if parameter that _argptr points to | |
0 | 79 } else { |
80 int nestedref; // referenced by a lexically nested function | |
81 } | |
82 int ctorinit; // it has been initialized in a ctor | |
83 int onstack; // 1: it has been allocated on the stack | |
84 // 2: on stack, run destructor anyway | |
85 int canassign; // it can be assigned to | |
86 Dsymbol aliassym; // if redone as alias to another symbol | |
87 Expression value; // when interpreting, this is the value | |
88 // (null if value not determinable) | |
89 version (DMDV2) { | |
90 VarDeclaration rundtor; // if !null, rundtor is tested at runtime to see | |
91 // if the destructor should be run. Used to prevent | |
92 // dtor calls on postblitted vars | |
93 } | |
94 | |
95 this(Loc loc, Type type, Identifier id, Initializer init) | |
96 { | |
97 super(id); | |
98 | |
98 | 99 debug |
100 { | |
0 | 101 if (!type && !init) |
102 { | |
103 writef("VarDeclaration('%s')\n", id.toChars()); | |
104 //*(char*)0=0; | |
105 } | |
106 } | |
107 assert(type || init); | |
108 this.type = type; | |
109 this.init = init; | |
98 | 110 version(_DH) |
111 { | |
112 this.htype = null; | |
113 this.hinit = null; | |
114 } | |
0 | 115 this.loc = loc; |
116 | |
98 | 117 /* TODO: |
118 #if DMDV1 | |
119 nestedref = 0; | |
120 #endif | |
121 ctorinit = 0; | |
122 aliassym = NULL; | |
123 onstack = 0; | |
124 canassign = 0; | |
125 value = NULL; | |
126 rundtor = NULL; | |
127 */ | |
0 | 128 nestedrefs = new FuncDeclarations(); |
129 } | |
130 | |
72 | 131 override Dsymbol syntaxCopy(Dsymbol s) |
0 | 132 { |
133 //printf("VarDeclaration.syntaxCopy(%s)\n", toChars()); | |
134 | |
135 VarDeclaration sv; | |
136 if (s) | |
137 { | |
138 sv = cast(VarDeclaration)s; | |
139 } | |
140 else | |
141 { | |
142 Initializer init = null; | |
143 if (this.init) | |
144 { | |
145 init = this.init.syntaxCopy(); | |
146 //init.isExpInitializer().exp.print(); | |
147 //init.isExpInitializer().exp.dump(0); | |
148 } | |
149 | |
150 sv = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, init); | |
151 sv.storage_class = storage_class; | |
152 } | |
153 | |
154 version (_DH) { | |
155 // Syntax copy for header file | |
156 if (!htype) // Don't overwrite original | |
157 { | |
158 if (type) // Make copy for both old and new instances | |
159 { htype = type.syntaxCopy(); | |
160 sv.htype = type.syntaxCopy(); | |
161 } | |
162 } | |
163 else // Make copy of original for new instance | |
164 sv.htype = htype.syntaxCopy(); | |
165 if (!hinit) | |
166 { | |
167 if (init) | |
168 { | |
169 hinit = init.syntaxCopy(); | |
170 sv.hinit = init.syntaxCopy(); | |
171 } | |
172 } | |
173 else | |
174 sv.hinit = hinit.syntaxCopy(); | |
175 } | |
176 return sv; | |
177 } | |
178 | |
72 | 179 override void semantic(Scope sc) |
0 | 180 { |
181 static if (false) { | |
182 printf("VarDeclaration.semantic('%s', parent = '%s')\n", toChars(), sc.parent.toChars()); | |
183 printf(" type = %s\n", type ? type.toChars() : "null"); | |
184 printf(" stc = x%x\n", sc.stc); | |
185 printf(" storage_class = x%x\n", storage_class); | |
186 printf("linkage = %d\n", sc.linkage); | |
187 //if (strcmp(toChars(), "mul") == 0) halt(); | |
188 } | |
189 | |
190 storage_class |= sc.stc; | |
191 if (storage_class & STC.STCextern && init) | |
192 error("extern symbols cannot have initializers"); | |
193 | |
194 /* If auto type inference, do the inference | |
195 */ | |
196 int inferred = 0; | |
197 if (!type) | |
198 { | |
199 inuse++; | |
200 type = init.inferType(sc); | |
201 inuse--; | |
202 inferred = 1; | |
203 | |
204 /* This is a kludge to support the existing syntax for RAII | |
205 * declarations. | |
206 */ | |
207 storage_class &= ~STC.STCauto; | |
208 originalType = type; | |
209 } | |
210 else | |
211 { | |
212 if (!originalType) | |
213 originalType = type; | |
214 | |
215 type = type.semantic(loc, sc); | |
216 } | |
217 //printf(" semantic type = %s\n", type ? type.toChars() : "null"); | |
218 | |
219 type.checkDeprecated(loc, sc); | |
220 linkage = sc.linkage; | |
221 this.parent = sc.parent; | |
222 //printf("this = %p, parent = %p, '%s'\n", this, parent, parent.toChars()); | |
223 protection = sc.protection; | |
224 //printf("sc.stc = %x\n", sc.stc); | |
225 //printf("storage_class = x%x\n", storage_class); | |
226 | |
227 version (DMDV2) { | |
228 if (storage_class & STC.STCgshared && global.params.safe && !sc.module_.safe) | |
229 { | |
230 error("__gshared not allowed in safe mode; use shared"); | |
231 } | |
232 } | |
233 | |
234 Dsymbol parent = toParent(); | |
235 FuncDeclaration fd = parent.isFuncDeclaration(); | |
236 | |
237 Type tb = type.toBasetype(); | |
238 if (tb.ty == TY.Tvoid && !(storage_class & STC.STClazy)) | |
239 { error("voids have no value"); | |
240 type = Type.terror; | |
241 tb = type; | |
242 } | |
243 if (tb.ty == TY.Tfunction) | |
244 { error("cannot be declared to be a function"); | |
245 type = Type.terror; | |
246 tb = type; | |
247 } | |
248 if (tb.ty == TY.Tstruct) | |
249 { TypeStruct ts = cast(TypeStruct)tb; | |
250 | |
251 if (!ts.sym.members) | |
252 { | |
253 error("no definition of struct %s", ts.toChars()); | |
254 } | |
255 } | |
256 | |
257 if (tb.ty == TY.Ttuple) | |
258 { /* Instead, declare variables for each of the tuple elements | |
259 * and add those. | |
260 */ | |
261 TypeTuple tt = cast(TypeTuple)tb; | |
262 size_t nelems = Argument.dim(tt.arguments); | |
263 Objects exps = new Objects(); | |
264 exps.setDim(nelems); | |
265 Expression ie = init ? init.toExpression() : null; | |
266 | |
267 for (size_t i = 0; i < nelems; i++) | |
268 { Argument arg = Argument.getNth(tt.arguments, i); | |
269 | |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
270 OutBuffer buf = new OutBuffer(); |
53 | 271 ///buf.printf("_%s_field_%zu", ident.toChars(), i); |
272 buf.printf("_%s_field_%s", ident.toChars(), i); | |
0 | 273 buf.writeByte(0); |
274 string name = buf.extractString(); | |
275 Identifier id = new Identifier(name, TOK.TOKidentifier); | |
276 | |
277 Expression einit = ie; | |
278 if (ie && ie.op == TOK.TOKtuple) | |
279 { einit = cast(Expression)(cast(TupleExp)ie).exps.data[i]; | |
280 } | |
281 Initializer ti = init; | |
282 if (einit) | |
283 { ti = new ExpInitializer(einit.loc, einit); | |
284 } | |
285 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
286 auto v = new VarDeclaration(loc, arg.type, id, ti); |
0 | 287 //printf("declaring field %s of type %s\n", v.toChars(), v.type.toChars()); |
288 v.semantic(sc); | |
289 | |
290 if (sc.scopesym) | |
291 { //printf("adding %s to %s\n", v.toChars(), sc.scopesym.toChars()); | |
292 if (sc.scopesym.members) | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
293 sc.scopesym.members.push(v); |
0 | 294 } |
295 | |
296 Expression e = new DsymbolExp(loc, v); | |
297 exps.data[i] = cast(void*)e; | |
298 } | |
299 TupleDeclaration v2 = new TupleDeclaration(loc, ident, exps); | |
300 v2.isexp = 1; | |
301 aliassym = v2; | |
302 return; | |
303 } | |
304 | |
305 Lagain: | |
306 /* Storage class can modify the type | |
307 */ | |
308 type = type.addStorageClass(storage_class); | |
309 | |
310 /* Adjust storage class to reflect type | |
311 */ | |
312 if (type.isConst()) | |
313 { storage_class |= STC.STCconst; | |
314 if (type.isShared()) | |
315 storage_class |= STC.STCshared; | |
316 } | |
317 else if (type.isInvariant()) | |
318 storage_class |= STC.STCimmutable; | |
319 else if (type.isShared()) | |
320 storage_class |= STC.STCshared; | |
321 | |
322 if (isSynchronized()) | |
323 { | |
324 error("variable %s cannot be synchronized", toChars()); | |
325 } | |
326 else if (isOverride()) | |
327 { | |
328 error("override cannot be applied to variable"); | |
329 } | |
330 else if (isAbstract()) | |
331 { | |
332 error("abstract cannot be applied to variable"); | |
333 } | |
334 else if (storage_class & STC.STCfinal) | |
335 { | |
336 error("final cannot be applied to variable"); | |
337 } | |
338 | |
339 if (storage_class & (STC.STCstatic | STC.STCextern | STC.STCmanifest | STC.STCtemplateparameter | STC.STCtls | STC.STCgshared)) | |
340 { | |
341 } | |
342 else | |
343 { | |
344 AggregateDeclaration aad = sc.anonAgg; | |
345 if (!aad) | |
346 aad = parent.isAggregateDeclaration(); | |
347 if (aad) | |
348 { | |
349 ///version (DMDV2) { | |
350 assert(!(storage_class & (STC.STCextern | STC.STCstatic | STC.STCtls | STC.STCgshared))); | |
351 | |
352 if (storage_class & (STC.STCconst | STC.STCimmutable) && init) | |
353 { | |
354 if (!type.toBasetype().isTypeBasic()) | |
355 storage_class |= STC.STCstatic; | |
356 } | |
357 else | |
358 ///} | |
359 aad.addField(sc, this); | |
360 } | |
361 | |
362 InterfaceDeclaration id = parent.isInterfaceDeclaration(); | |
363 if (id) | |
364 { | |
365 error("field not allowed in interface"); | |
366 } | |
367 | |
368 /* Templates cannot add fields to aggregates | |
369 */ | |
370 TemplateInstance ti = parent.isTemplateInstance(); | |
371 if (ti) | |
372 { | |
373 // Take care of nested templates | |
374 while (1) | |
375 { | |
376 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance(); | |
377 if (!ti2) | |
378 break; | |
379 ti = ti2; | |
380 } | |
381 | |
382 // If it's a member template | |
383 AggregateDeclaration ad = ti.tempdecl.isMember(); | |
384 if (ad && storage_class != STC.STCundefined) | |
385 { | |
386 error("cannot use template to add field to aggregate '%s'", ad.toChars()); | |
387 } | |
388 } | |
389 } | |
390 | |
391 version (DMDV2) { | |
392 if ((storage_class & (STC.STCref | STC.STCparameter | STC.STCforeach)) == STC.STCref && ident != Id.This) | |
393 { | |
394 error("only parameters or foreach declarations can be ref"); | |
395 } | |
396 } | |
397 | |
398 if (type.isauto() && !noauto) | |
399 { | |
400 if (storage_class & (STC.STCfield | STC.STCout | STC.STCref | STC.STCstatic | STC.STCmanifest | STC.STCtls | STC.STCgshared) || !fd) | |
401 { | |
402 error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope"); | |
403 } | |
404 | |
405 if (!(storage_class & (STC.STCauto | STC.STCscope))) | |
406 { | |
407 if (!(storage_class & STC.STCparameter) && ident != Id.withSym) | |
408 error("reference to scope class must be scope"); | |
409 } | |
410 } | |
411 | |
412 if ((isConst() || isInvariant()) && !init && !fd) | |
413 { | |
414 // Initialize by constructor only | |
415 storage_class |= STC.STCctorinit; | |
416 } | |
417 | |
418 if (init) | |
419 storage_class |= STC.STCinit; // remember we had an explicit initializer | |
420 else if (storage_class & STC.STCmanifest) | |
421 error("manifest constants must have initializers"); | |
422 | |
423 TOK op = TOK.TOKconstruct; | |
424 if (!init && !sc.inunion && !isStatic() && fd && | |
425 (!(storage_class & (STC.STCfield | STC.STCin | STC.STCforeach | STC.STCparameter)) || (storage_class & STC.STCout)) && | |
426 type.size() != 0) | |
427 { | |
428 // Provide a default initializer | |
429 //printf("Providing default initializer for '%s'\n", toChars()); | |
430 if (type.ty == TY.Tstruct && | |
431 (cast(TypeStruct)type).sym.zeroInit) | |
432 { /* If a struct is all zeros, as a special case | |
433 * set it's initializer to the integer 0. | |
434 * In AssignExp.toElem(), we check for this and issue | |
435 * a memset() to initialize the struct. | |
436 * Must do same check in interpreter. | |
437 */ | |
438 Expression e = new IntegerExp(loc, 0, Type.tint32); | |
439 Expression e1; | |
440 e1 = new VarExp(loc, this); | |
441 e = new AssignExp(loc, e1, e); | |
442 e.op = TOK.TOKconstruct; | |
443 e.type = e1.type; // don't type check this, it would fail | |
444 init = new ExpInitializer(loc, e); | |
445 return; | |
446 } | |
447 else if (type.ty == TY.Ttypedef) | |
448 { TypeTypedef td = cast(TypeTypedef)type; | |
449 if (td.sym.init) | |
450 { init = td.sym.init; | |
451 ExpInitializer ie = init.isExpInitializer(); | |
452 if (ie) | |
453 // Make copy so we can modify it | |
454 init = new ExpInitializer(ie.loc, ie.exp); | |
455 } | |
456 else | |
457 init = getExpInitializer(); | |
458 } | |
459 else | |
460 { | |
461 init = getExpInitializer(); | |
462 } | |
463 // Default initializer is always a blit | |
464 op = TOK.TOKblit; | |
465 } | |
466 | |
467 if (init) | |
468 { | |
469 sc = sc.push(); | |
470 sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref); | |
471 | |
472 ArrayInitializer ai = init.isArrayInitializer(); | |
473 if (ai && tb.ty == TY.Taarray) | |
474 { | |
475 init = ai.toAssocArrayInitializer(); | |
476 } | |
477 | |
478 StructInitializer si = init.isStructInitializer(); | |
479 ExpInitializer ei = init.isExpInitializer(); | |
480 | |
481 // See if initializer is a NewExp that can be allocated on the stack | |
482 if (ei && isScope() && ei.exp.op == TOK.TOKnew) | |
483 { NewExp ne = cast(NewExp)ei.exp; | |
484 if (!(ne.newargs && ne.newargs.dim)) | |
485 { ne.onstack = 1; | |
486 onstack = 1; | |
487 if (type.isBaseOf(ne.newtype.semantic(loc, sc), null)) | |
488 onstack = 2; | |
489 } | |
490 } | |
491 | |
492 // If inside function, there is no semantic3() call | |
493 if (sc.func) | |
494 { | |
495 // If local variable, use AssignExp to handle all the various | |
496 // possibilities. | |
497 if (fd && | |
498 !(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) && | |
499 !init.isVoidInitializer()) | |
500 { | |
501 //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars()); | |
502 if (!ei) | |
503 { | |
504 Expression e = init.toExpression(); | |
505 if (!e) | |
506 { | |
507 init = init.semantic(sc, type); | |
508 e = init.toExpression(); | |
509 if (!e) | |
510 { error("is not a static and cannot have static initializer"); | |
511 return; | |
512 } | |
513 } | |
514 ei = new ExpInitializer(init.loc, e); | |
515 init = ei; | |
516 } | |
517 | |
518 Expression e1 = new VarExp(loc, this); | |
519 | |
520 Type t = type.toBasetype(); | |
521 if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout))) | |
522 { | |
523 ei.exp = ei.exp.semantic(sc); | |
524 if (!ei.exp.implicitConvTo(type)) | |
525 { | |
526 int dim = cast(int)(cast(TypeSArray)t).dim.toInteger(); /// | |
527 // If multidimensional static array, treat as one large array | |
528 while (1) | |
529 { | |
530 t = t.nextOf().toBasetype(); | |
531 if (t.ty != TY.Tsarray) | |
532 break; | |
533 dim *= (cast(TypeSArray)t).dim.toInteger(); | |
534 e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex)); | |
535 } | |
536 } | |
537 e1 = new SliceExp(loc, e1, null, null); | |
538 } | |
539 else if (t.ty == TY.Tstruct) | |
540 { | |
541 ei.exp = ei.exp.semantic(sc); | |
98 | 542 ei.exp = resolveProperties(sc, ei.exp); |
543 StructDeclaration sd = (cast(TypeStruct)t).sym; | |
544 version (DMDV2) | |
545 { | |
0 | 546 /* Look to see if initializer is a call to the constructor |
547 */ | |
548 if (sd.ctor && // there are constructors | |
549 ei.exp.type.ty == TY.Tstruct && // rvalue is the same struct | |
550 (cast(TypeStruct)ei.exp.type).sym == sd && | |
551 ei.exp.op == TOK.TOKstar) | |
552 { | |
553 /* Look for form of constructor call which is: | |
554 * *__ctmp.ctor(arguments...) | |
555 */ | |
556 PtrExp pe = cast(PtrExp)ei.exp; | |
557 if (pe.e1.op == TOK.TOKcall) | |
558 { CallExp ce = cast(CallExp)pe.e1; | |
559 if (ce.e1.op == TOK.TOKdotvar) | |
560 { DotVarExp dve = cast(DotVarExp)ce.e1; | |
561 if (dve.var.isCtorDeclaration()) | |
562 { /* It's a constructor call, currently constructing | |
563 * a temporary __ctmp. | |
564 */ | |
565 /* Before calling the constructor, initialize | |
566 * variable with a bit copy of the default | |
567 * initializer | |
568 */ | |
569 Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc)); | |
570 e.op = TOK.TOKblit; | |
571 e.type = t; | |
572 ei.exp = new CommaExp(loc, e, ei.exp); | |
573 | |
574 /* Replace __ctmp being constructed with e1 | |
575 */ | |
576 dve.e1 = e1; | |
577 return; | |
578 } | |
579 } | |
580 } | |
581 } | |
582 } | |
583 if (!ei.exp.implicitConvTo(type)) | |
73 | 584 { |
98 | 585 Type *ti = ei.exp.type.toBasetype(); |
586 // Look for constructor first | |
587 if (sd.ctor && | |
588 /* Initializing with the same type is done differently | |
589 */ | |
590 !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc))) | |
591 { | |
592 // Rewrite as e1.ctor(arguments) | |
593 Expression ector = new DotIdExp(loc, e1, Id.ctor); | |
594 ei.exp = new CallExp(loc, ector, ei.exp); | |
595 } | |
596 else | |
73 | 597 /* Look for opCall |
598 * See bugzilla 2702 for more discussion | |
599 */ | |
98 | 600 |
73 | 601 // Don't cast away invariant or mutability in initializer |
602 if (search_function(sd, Id.call) && | |
603 /* Initializing with the same type is done differently | |
604 */ | |
605 !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc))) | |
606 { // Rewrite as e1.call(arguments) | |
607 Expression eCall = new DotIdExp(loc, e1, Id.call); | |
608 ei.exp = new CallExp(loc, eCall, ei.exp); | |
609 } | |
0 | 610 } |
611 } | |
612 ei.exp = new AssignExp(loc, e1, ei.exp); | |
613 ei.exp.op = op; | |
614 canassign++; | |
615 ei.exp = ei.exp.semantic(sc); | |
616 canassign--; | |
617 ei.exp.optimize(WANT.WANTvalue); | |
618 } | |
619 else | |
620 { | |
621 init = init.semantic(sc, type); | |
622 } | |
623 } | |
624 else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) || | |
98 | 625 type.isConst() || type.isInvariant() || |
626 parent.isAggregateDeclaration()) | |
0 | 627 { |
628 /* Because we may need the results of a const declaration in a | |
629 * subsequent type, such as an array dimension, before semantic2() | |
630 * gets ordinarily run, try to run semantic2() now. | |
631 * Ignore failure. | |
632 */ | |
633 | |
634 if (!global.errors && !inferred) | |
635 { | |
636 uint errors = global.errors; | |
637 global.gag++; | |
638 //printf("+gag\n"); | |
639 Expression e; | |
640 Initializer i2 = init; | |
641 inuse++; | |
642 if (ei) | |
643 { | |
644 e = ei.exp.syntaxCopy(); | |
645 e = e.semantic(sc); | |
646 e = e.implicitCastTo(sc, type); | |
647 } | |
648 else if (si || ai) | |
649 { i2 = init.syntaxCopy(); | |
650 i2 = i2.semantic(sc, type); | |
651 } | |
652 inuse--; | |
653 global.gag--; | |
654 //printf("-gag\n"); | |
655 if (errors != global.errors) // if errors happened | |
656 { | |
657 if (global.gag == 0) | |
658 global.errors = errors; // act as if nothing happened | |
659 version (DMDV2) { | |
660 /* Save scope for later use, to try again | |
661 */ | |
87
b17640f0e4e8
Fixed a bug with a Scope.this(Scope enclosing) being called instead of Scope.clone() method (as a copy ctor replacement)
korDen
parents:
77
diff
changeset
|
662 scope_ = sc.clone(); |
0 | 663 scope_.setNoFree(); |
664 } | |
665 } | |
666 else if (ei) | |
667 { | |
668 if (isDataseg()) | |
669 /* static const/invariant does CTFE | |
670 */ | |
671 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
672 else | |
673 e = e.optimize(WANT.WANTvalue); | |
674 if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64) | |
675 { | |
676 ei.exp = e; // no errors, keep result | |
677 } | |
678 ///version (DMDV2) { | |
679 else | |
680 { | |
681 /* Save scope for later use, to try again | |
682 */ | |
87
b17640f0e4e8
Fixed a bug with a Scope.this(Scope enclosing) being called instead of Scope.clone() method (as a copy ctor replacement)
korDen
parents:
77
diff
changeset
|
683 scope_ = sc.clone(); |
0 | 684 scope_.setNoFree(); |
685 } | |
686 ///} | |
687 } | |
688 else | |
689 init = i2; // no errors, keep result | |
690 } | |
691 } | |
692 sc = sc.pop(); | |
693 } | |
694 } | |
695 | |
72 | 696 override void semantic2(Scope sc) |
0 | 697 { |
698 //printf("VarDeclaration.semantic2('%s')\n", toChars()); | |
699 if (init && !toParent().isFuncDeclaration()) | |
700 { | |
701 inuse++; | |
702 static if (false) { | |
703 ExpInitializer ei = init.isExpInitializer(); | |
704 if (ei) | |
705 { | |
706 ei.exp.dump(0); | |
707 printf("type = %p\n", ei.exp.type); | |
708 } | |
709 } | |
710 init = init.semantic(sc, type); | |
711 inuse--; | |
712 } | |
713 } | |
714 | |
72 | 715 override string kind() |
0 | 716 { |
717 return "variable"; | |
718 } | |
719 | |
72 | 720 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 721 { |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
722 StorageClassDeclaration.stcToCBuffer(buf, storage_class); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
723 |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
724 /* If changing, be sure and fix CompoundDeclarationStatement.toCBuffer() |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
725 * too. |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
726 */ |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
727 if (type) |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
728 type.toCBuffer(buf, ident, hgs); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
729 else |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
730 buf.writestring(ident.toChars()); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
731 if (init) |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
732 { |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
733 buf.writestring(" = "); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
734 ///version (DMDV2) { |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
735 ExpInitializer ie = init.isExpInitializer(); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
736 if (ie && (ie.exp.op == TOKconstruct || ie.exp.op == TOKblit)) |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
737 (cast(AssignExp)ie.exp).e2.toCBuffer(buf, hgs); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
738 else |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
739 ///} |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
740 init.toCBuffer(buf, hgs); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
741 } |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
742 buf.writeByte(';'); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
53
diff
changeset
|
743 buf.writenl(); |
0 | 744 } |
745 | |
746 version (_DH) { | |
747 Type htype; | |
748 Initializer hinit; | |
749 } | |
72 | 750 override bool needThis() |
0 | 751 { |
752 //printf("VarDeclaration.needThis(%s, x%x)\n", toChars(), storage_class); | |
753 return (storage_class & STC.STCfield) != 0; | |
754 } | |
755 | |
72 | 756 override bool isImportedSymbol() |
0 | 757 { |
758 if (protection == PROT.PROTexport && !init && (storage_class & STC.STCstatic || parent.isModule())) | |
759 return true; | |
760 | |
761 return false; | |
762 } | |
763 | |
72 | 764 override bool isDataseg() |
0 | 765 { |
766 static if (false) { | |
767 printf("VarDeclaration.isDataseg(%p, '%s')\n", this, toChars()); | |
768 printf("%x, %p, %p\n", storage_class & (STC.STCstatic | STC.STCconst), parent.isModule(), parent.isTemplateInstance()); | |
769 printf("parent = '%s'\n", parent.toChars()); | |
770 } | |
771 if (storage_class & STC.STCmanifest) | |
772 return false; | |
773 | |
774 Dsymbol parent = this.toParent(); | |
775 if (!parent && !(storage_class & STC.STCstatic)) | |
776 { | |
777 error("forward referenced"); | |
778 type = Type.terror; | |
779 return false; | |
780 } | |
781 | |
782 return canTakeAddressOf() && (storage_class & (STC.STCstatic | STC.STCextern | STC.STCtls | STC.STCgshared) || toParent().isModule() || toParent().isTemplateInstance()); | |
783 } | |
784 | |
72 | 785 override bool isThreadlocal() |
0 | 786 { |
787 //printf("VarDeclaration.isThreadlocal(%p, '%s')\n", this, toChars()); | |
788 static if (false) { /// || TARGET_OSX | |
789 /* To be thread-local, must use the __thread storage class. | |
790 * BUG: OSX doesn't support thread local yet. | |
791 */ | |
792 return isDataseg() && (storage_class & (STC.STCtls | STC.STCconst | STC.STCimmutable | STC.STCshared | STC.STCgshared)) == STC.STCtls; | |
793 } else { | |
794 /* Data defaults to being thread-local. It is not thread-local | |
795 * if it is immutable, const or shared. | |
796 */ | |
797 bool i = isDataseg() && !(storage_class & (STC.STCimmutable | STC.STCconst | STC.STCshared | STC.STCgshared)); | |
798 //printf("\treturn %d\n", i); | |
799 return i; | |
800 } | |
801 } | |
802 | |
72 | 803 override bool hasPointers() |
0 | 804 { |
805 //printf("VarDeclaration.hasPointers() %s, ty = %d\n", toChars(), type.ty); | |
806 return (!isDataseg() && type.hasPointers()); | |
807 } | |
808 | |
809 version (DMDV2) { | |
810 bool canTakeAddressOf() | |
811 { | |
812 static if (false) { | |
813 /* Global variables and struct/class fields of the form: | |
814 * const int x = 3; | |
815 * are not stored and hence cannot have their address taken. | |
816 */ | |
817 if ((isConst() || isInvariant()) && (storage_class & STC.STCinit) && (!(storage_class & (STC.STCstatic | STC.STCextern)) || (storage_class & STC.STCfield)) && | |
818 (!parent || toParent().isModule() || toParent().isTemplateInstance()) && type.toBasetype().isTypeBasic()) | |
819 { | |
820 return false; | |
821 } | |
822 } else { | |
823 if (storage_class & STC.STCmanifest) | |
824 return false; | |
825 } | |
826 return true; | |
827 } | |
828 | |
12
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
829 /****************************************** |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
830 * Return TRUE if variable needs to call the destructor. |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
831 */ |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
832 bool needsAutoDtor() |
0 | 833 { |
12
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
834 //printf("VarDeclaration.needsAutoDtor() %s\n", toChars()); |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
835 |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
836 if (noauto || storage_class & STCnodtor) |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
837 return false; |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
838 |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
839 // Destructors for structs and arrays of structs |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
840 Type tv = type.toBasetype(); |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
841 while (tv.ty == Tsarray) |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
842 { |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
843 TypeSArray ta = cast(TypeSArray)tv; |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
844 tv = tv.nextOf().toBasetype(); |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
845 } |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
846 if (tv.ty == Tstruct) |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
847 { |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
848 TypeStruct ts = cast(TypeStruct)tv; |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
849 StructDeclaration sd = ts.sym; |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
850 if (sd.dtor) |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
851 return true; |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
852 } |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
853 |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
854 // Destructors for classes |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
855 if (storage_class & (STCauto | STCscope)) |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
856 { |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
857 if (type.isClassHandle()) |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
858 return true; |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
859 } |
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
860 return false; |
0 | 861 } |
862 } | |
863 | |
864 /****************************************** | |
865 * If a variable has an auto destructor call, return call for it. | |
866 * Otherwise, return null. | |
867 */ | |
868 Expression callAutoDtor(Scope sc) | |
869 { | |
870 Expression e = null; | |
871 | |
872 //printf("VarDeclaration.callAutoDtor() %s\n", toChars()); | |
873 | |
874 if (noauto || storage_class & STC.STCnodtor) | |
875 return null; | |
876 | |
877 // Destructors for structs and arrays of structs | |
878 bool array = false; | |
879 Type tv = type.toBasetype(); | |
880 while (tv.ty == TY.Tsarray) | |
881 { | |
882 TypeSArray ta = cast(TypeSArray)tv; | |
883 array = true; | |
884 tv = tv.nextOf().toBasetype(); | |
885 } | |
886 if (tv.ty == TY.Tstruct) | |
887 { | |
888 TypeStruct ts = cast(TypeStruct)tv; | |
889 StructDeclaration sd = ts.sym; | |
890 if (sd.dtor) | |
891 { | |
892 if (array) | |
893 { | |
894 // Typeinfo.destroy(cast(void*)&v); | |
895 Expression ea = new SymOffExp(loc, this, 0, 0); | |
896 ea = new CastExp(loc, ea, Type.tvoid.pointerTo()); | |
897 Expressions args = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
898 args.push(ea); |
0 | 899 |
900 Expression et = type.getTypeInfo(sc); | |
901 et = new DotIdExp(loc, et, Id.destroy); | |
902 | |
903 e = new CallExp(loc, et, args); | |
904 } | |
905 else | |
906 { | |
907 e = new VarExp(loc, this); | |
908 e = new DotVarExp(loc, e, sd.dtor, 0); | |
909 e = new CallExp(loc, e); | |
910 } | |
911 return e; | |
912 } | |
913 } | |
914 | |
915 // Destructors for classes | |
916 if (storage_class & (STC.STCauto | STC.STCscope)) | |
917 { | |
918 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass) | |
919 { | |
920 /* We can do better if there's a way with onstack | |
921 * classes to determine if there's no way the monitor | |
922 * could be set. | |
923 */ | |
924 //if (cd.isInterfaceDeclaration()) | |
925 //error("interface %s cannot be scope", cd.toChars()); | |
926 if (1 || onstack || cd.dtors.dim) // if any destructors | |
927 { | |
928 // delete this; | |
929 Expression ec = new VarExp(loc, this); | |
930 e = new DeleteExp(loc, ec); | |
931 e.type = Type.tvoid; | |
932 break; | |
933 } | |
934 } | |
935 } | |
936 return e; | |
937 } | |
938 | |
939 /**************************** | |
940 * Get ExpInitializer for a variable, if there is one. | |
941 */ | |
942 ExpInitializer getExpInitializer() | |
943 { | |
944 ExpInitializer ei; | |
945 | |
946 if (init) | |
947 ei = init.isExpInitializer(); | |
948 else | |
949 { | |
950 Expression e = type.defaultInit(loc); | |
951 if (e) | |
952 ei = new ExpInitializer(loc, e); | |
953 else | |
954 ei = null; | |
955 } | |
956 return ei; | |
957 } | |
958 | |
959 /******************************************* | |
960 * If variable has a constant expression initializer, get it. | |
961 * Otherwise, return null. | |
962 */ | |
963 Expression getConstInitializer() | |
964 { | |
965 if ((isConst() || isInvariant() || storage_class & STC.STCmanifest) && storage_class & STC.STCinit) | |
966 { | |
967 ExpInitializer ei = getExpInitializer(); | |
968 if (ei) | |
969 return ei.exp; | |
970 } | |
971 | |
972 return null; | |
973 } | |
974 | |
72 | 975 override void checkCtorConstInit() |
0 | 976 { |
977 static if (false) { /* doesn't work if more than one static ctor */ | |
978 if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) | |
979 error("missing initializer in static constructor for const variable"); | |
980 } | |
981 } | |
982 | |
983 /************************************ | |
984 * Check to see if this variable is actually in an enclosing function | |
985 * rather than the current one. | |
986 */ | |
987 void checkNestedReference(Scope sc, Loc loc) | |
988 { | |
989 if (parent && !isDataseg() && parent != sc.parent && !(storage_class & STC.STCmanifest)) | |
990 { | |
991 // The function that this variable is in | |
992 FuncDeclaration fdv = toParent().isFuncDeclaration(); | |
993 // The current function | |
994 FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); | |
995 | |
996 if (fdv && fdthis && fdv !is fdthis) | |
997 { | |
998 if (loc.filename) | |
999 fdthis.getLevel(loc, fdv); | |
1000 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
1001 foreach (f; nestedrefs) |
0 | 1002 { |
1003 if (f == fdthis) | |
1004 goto L1; | |
1005 } | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
1006 nestedrefs.push(fdthis); |
0 | 1007 L1: ; |
1008 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
1009 foreach (s; fdv.closureVars) |
0 | 1010 { |
1011 if (s == this) | |
1012 goto L2; | |
1013 } | |
1014 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
1015 fdv.closureVars.push(this); |
0 | 1016 L2: ; |
1017 | |
1018 //printf("fdthis is %s\n", fdthis.toChars()); | |
1019 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); | |
1020 } | |
1021 } | |
1022 } | |
1023 | |
72 | 1024 override Dsymbol toAlias() |
0 | 1025 { |
1026 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); | |
1027 assert(this !is aliassym); | |
1028 return aliassym ? aliassym.toAlias() : this; | |
1029 } | |
1030 | |
72 | 1031 override Symbol* toSymbol() |
0 | 1032 { |
1033 //printf("VarDeclaration.toSymbol(%s)\n", toChars()); | |
1034 //if (needThis()) *(char*)0=0; | |
1035 assert(!needThis()); | |
1036 if (!csym) | |
1037 { | |
1038 Symbol* s; | |
1039 TYPE* t; | |
1040 string id; | |
1041 | |
1042 if (isDataseg()) | |
1043 id = mangle(); | |
1044 else | |
1045 id = ident.toChars(); | |
1046 | |
1047 s = symbol_calloc(toStringz(id)); | |
1048 | |
1049 if (storage_class & (STC.STCout | STC.STCref)) | |
1050 { | |
1051 if (global.params.symdebug && storage_class & STC.STCparameter) | |
1052 { | |
1053 t = type_alloc(TYM.TYnptr); // should be TYref, but problems in back end | |
1054 t.Tnext = type.toCtype(); | |
1055 t.Tnext.Tcount++; | |
1056 } | |
1057 else | |
1058 t = type_fake(TYM.TYnptr); | |
1059 } | |
1060 else if (storage_class & STC.STClazy) | |
1061 t = type_fake(TYM.TYdelegate); // Tdelegate as C type | |
1062 else if (isParameter()) | |
1063 t = type.toCParamtype(); | |
1064 else | |
1065 t = type.toCtype(); | |
1066 | |
1067 t.Tcount++; | |
1068 | |
1069 if (isDataseg()) | |
1070 { | |
1071 if (isThreadlocal()) | |
1072 { | |
1073 /* Thread local storage | |
1074 */ | |
1075 TYPE* ts = t; | |
1076 ts.Tcount++; // make sure a different t is allocated | |
1077 type_setty(&t, t.Tty | mTY.mTYthread); | |
1078 ts.Tcount--; | |
1079 | |
1080 if (global.params.vtls) | |
1081 { | |
1082 string p = loc.toChars(); | |
1083 writef("%s: %s is thread local\n", p ? p : "", toChars()); | |
1084 } | |
1085 } | |
1086 | |
1087 s.Sclass = SC.SCextern; | |
1088 s.Sfl = FL.FLextern; | |
1089 slist_add(s); | |
1090 } | |
1091 else | |
1092 { | |
1093 s.Sclass = SC.SCauto; | |
1094 s.Sfl = FL.FLauto; | |
1095 | |
1096 if (nestedrefs.dim) | |
1097 { | |
1098 /* Symbol is accessed by a nested function. Make sure | |
1099 * it is not put in a register, and that the optimizer | |
1100 * assumes it is modified across function calls and pointer | |
1101 * dereferences. | |
1102 */ | |
1103 //printf("\tnested ref, not register\n"); | |
1104 type_setcv(&t, t.Tty | mTY.mTYvolatile); | |
1105 } | |
1106 } | |
1107 | |
1108 mangle_t m = 0; | |
1109 switch (linkage) | |
1110 { | |
1111 case LINK.LINKwindows: | |
1112 m = mTYman.mTYman_std; | |
1113 break; | |
1114 | |
1115 case LINK.LINKpascal: | |
1116 m = mTYman.mTYman_pas; | |
1117 break; | |
1118 | |
1119 case LINK.LINKc: | |
1120 m = mTYman.mTYman_c; | |
1121 break; | |
1122 | |
1123 case LINK.LINKd: | |
1124 m = mTYman.mTYman_d; | |
1125 break; | |
1126 | |
1127 case LINK.LINKcpp: | |
1128 m = mTYman.mTYman_cpp; | |
1129 break; | |
1130 | |
1131 default: | |
1132 writef("linkage = %d\n", linkage); | |
1133 assert(0); | |
1134 } | |
1135 type_setmangle(&t, m); | |
1136 s.Stype = t; | |
1137 | |
1138 csym = s; | |
1139 } | |
1140 return csym; | |
1141 } | |
1142 | |
72 | 1143 override void toObjFile(int multiobj) // compile to .obj file |
0 | 1144 { |
1145 Symbol* s; | |
1146 uint sz; | |
1147 Dsymbol parent; | |
1148 | |
1149 //printf("VarDeclaration.toObjFile(%p '%s' type=%s) protection %d\n", this, toChars(), type.toChars(), protection); | |
1150 //printf("\talign = %d\n", type.alignsize()); | |
1151 | |
1152 if (aliassym) | |
1153 { | |
1154 toAlias().toObjFile(0); | |
1155 return; | |
1156 } | |
1157 | |
1158 version (DMDV2) { | |
1159 // Do not store variables we cannot take the address of | |
1160 if (!canTakeAddressOf()) | |
1161 { | |
1162 return; | |
1163 } | |
1164 } | |
1165 | |
1166 if (isDataseg() && !(storage_class & STC.STCextern)) | |
1167 { | |
1168 s = toSymbol(); | |
1169 sz = cast(uint)type.size(); | |
1170 | |
1171 parent = this.toParent(); | |
1172 /// version (DMDV1) { /* private statics should still get a global symbol, in case | |
1173 /// * another module inlines a function that references it. | |
1174 /// */ | |
1175 /// if (/*protection == PROT.PROTprivate ||*/ | |
1176 /// !parent || parent.ident == null || parent.isFuncDeclaration()) | |
1177 /// { | |
1178 /// s.Sclass = SC.SCstatic; | |
1179 /// } | |
1180 /// else | |
1181 /// } | |
1182 { | |
1183 if (storage_class & STC.STCcomdat) | |
1184 s.Sclass = SC.SCcomdat; | |
1185 else | |
1186 s.Sclass = SC.SCglobal; | |
1187 | |
1188 do | |
1189 { | |
1190 /* Global template data members need to be in comdat's | |
1191 * in case multiple .obj files instantiate the same | |
1192 * template with the same types. | |
1193 */ | |
1194 if (parent.isTemplateInstance() && !parent.isTemplateMixin()) | |
1195 { | |
1196 version (DMDV1) { | |
1197 /* These symbol constants have already been copied, | |
1198 * so no reason to output them. | |
1199 * Note that currently there is no way to take | |
1200 * the address of such a const. | |
1201 */ | |
1202 if (isConst() && type.toBasetype().ty != TY.Tsarray && init && init.isExpInitializer()) | |
1203 return; | |
1204 } | |
1205 s.Sclass = SC.SCcomdat; | |
1206 break; | |
1207 } | |
1208 parent = parent.parent; | |
1209 } while (parent); | |
1210 } | |
1211 | |
1212 s.Sfl = FL.FLdata; | |
1213 | |
1214 if (init) | |
1215 { | |
1216 s.Sdt = init.toDt(); | |
1217 | |
1218 // Look for static array that is block initialized | |
1219 Type tb; | |
1220 ExpInitializer ie = init.isExpInitializer(); | |
1221 | |
1222 tb = type.toBasetype(); | |
1223 if (tb.ty == TY.Tsarray && ie | |
1224 && !tb.nextOf().equals(ie.exp.type.toBasetype().nextOf()) | |
1225 && ie.exp.implicitConvTo(tb.nextOf())) | |
1226 { | |
1227 int dim = cast(int)(cast(TypeSArray)tb).dim.toInteger(); | |
1228 | |
1229 // Duplicate Sdt 'dim-1' times, as we already have the first one | |
1230 while (--dim > 0) | |
1231 { | |
1232 ie.exp.toDt(&s.Sdt); | |
1233 } | |
1234 } | |
1235 } | |
1236 else if (storage_class & STC.STCextern) | |
1237 { | |
1238 s.Sclass = SC.SCextern; | |
1239 s.Sfl = FL.FLextern; | |
1240 s.Sdt = null; | |
1241 // BUG: if isExport(), shouldn't we make it dllimport? | |
1242 return; | |
1243 } | |
1244 else | |
1245 { | |
1246 type.toDt(&s.Sdt); | |
1247 } | |
1248 dt_optimize(s.Sdt); | |
1249 | |
1250 // See if we can convert a comdat to a comdef, | |
1251 // which saves on exe file space. | |
1252 if (s.Sclass == SC.SCcomdat && | |
1253 s.Sdt && | |
1254 s.Sdt.dt == DT.DT_azeros && | |
1255 s.Sdt.DTnext is null && | |
1256 !isThreadlocal()) | |
1257 { | |
1258 s.Sclass = SC.SCglobal; | |
1259 s.Sdt.dt = DT.DT_common; | |
1260 } | |
1261 | |
1262 version (ELFOBJ_OR_MACHOBJ) { // Burton | |
1263 if (s.Sdt && s.Sdt.dt == DT.DT_azeros && s.Sdt.DTnext is null) | |
1264 s.Sseg = Segment.UDATA; | |
1265 else | |
1266 s.Sseg = Segment.DATA; | |
1267 } | |
1268 if (sz) | |
1269 { | |
1270 outdata(s); | |
1271 if (isExport()) | |
1272 obj_export(s, 0); | |
1273 } | |
1274 } | |
1275 } | |
1276 | |
72 | 1277 override int cvMember(ubyte* p) |
0 | 1278 { |
1279 assert(false); | |
1280 } | |
1281 | |
1282 // Eliminate need for dynamic_cast | |
72 | 1283 override VarDeclaration isVarDeclaration() { return this; } |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1284 } |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
1285 |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
1286 alias Vector!VarDeclaration VarDeclarations; |