comparison dmd/TypeStruct.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 8c2c7b7579f8
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
1 module dmd.TypeStruct;
2
3 import dmd.Type;
4 import dmd.StructDeclaration;
5 import dmd.Declaration;
6 import dmd.STC;
7 import dmd.MOD;
8 import dmd.OutBuffer;
9 import dmd.DotVarExp;
10 import dmd.TemplateMixin;
11 import dmd.DotTemplateExp;
12 import dmd.DsymbolExp;
13 import dmd.TypeExp;
14 import dmd.EnumMember;
15 import dmd.Id;
16 import dmd.DotIdExp;
17 import dmd.ScopeExp;
18 import dmd.TupleExp;
19 import dmd.TemplateDeclaration;
20 import dmd.OverloadSet;
21 import dmd.Import;
22 import dmd.DotExp;
23 import dmd.ErrorExp;
24 import dmd.Loc;
25 import dmd.Scope;
26 import dmd.Dsymbol;
27 import dmd.HdrGenState;
28 import dmd.Expression;
29 import dmd.Identifier;
30 import dmd.MATCH;
31 import dmd.ArrayTypes;
32 import dmd.TemplateInstance;
33 import dmd.FuncDeclaration;
34 import dmd.VarExp;
35 import dmd.CommaExp;
36 import dmd.ThisExp;
37 import dmd.SymbolDeclaration;
38 import dmd.TypeInfoDeclaration;
39 import dmd.TypeInfoStructDeclaration;
40 import dmd.TY;
41 import dmd.TOK;
42 import dmd.Global;
43 import dmd.VarDeclaration;
44 import dmd.Util;
45 import dmd.expression.Util;
46
47 import dmd.backend.TYPE;
48 import dmd.backend.dt_t;
49 import dmd.backend.Symbol;
50 import dmd.backend.Util;
51 import dmd.backend.STR;
52 import dmd.backend.TYM;
53 import dmd.backend.Classsym;
54 import dmd.backend.SC;
55 import dmd.backend.LIST;
56
57 import std.string : toStringz;
58
59 class TypeStruct : Type
60 {
61 StructDeclaration sym;
62
63 this(StructDeclaration sym)
64 {
65 super(TY.Tstruct);
66 this.sym = sym;
67 }
68 version (DumbClone) {
69 } else {
70 final TypeStruct cloneTo(TypeStruct t)
71 {
72 super.cloneTo(t);
73 assert(t.sym is sym);
74 return t;
75 }
76
77 TypeStruct clone()
78 {
79 assert(this.classinfo == TypeStruct.classinfo);
80 return cloneTo(new TypeStruct(sym));
81 }
82 }
83 ulong size(Loc loc)
84 {
85 return sym.size(loc);
86 }
87
88 uint alignsize()
89 {
90 uint sz;
91
92 sym.size(Loc(0)); // give error for forward references
93 sz = sym.alignsize;
94 if (sz > sym.structalign)
95 sz = sym.structalign;
96 return sz;
97 }
98
99 string toChars()
100 {
101 assert(false);
102 }
103
104 Type syntaxCopy()
105 {
106 assert(false);
107 }
108
109 Type semantic(Loc loc, Scope sc)
110 {
111 //printf("TypeStruct.semantic('%s')\n", sym.toChars());
112
113 /* Cannot do semantic for sym because scope chain may not
114 * be right.
115 */
116 //sym.semantic(sc);
117
118 return merge();
119 }
120
121 Dsymbol toDsymbol(Scope sc)
122 {
123 return sym;
124 }
125
126 void toDecoBuffer(OutBuffer buf, int flag)
127 {
128 string name = sym.mangle();
129 //printf("TypeStruct.toDecoBuffer('%s') = '%s'\n", toChars(), name);
130 Type.toDecoBuffer(buf, flag);
131 buf.printf("%s", name);
132 }
133
134 void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
135 {
136 if (mod != this.mod)
137 {
138 toCBuffer3(buf, hgs, mod);
139 return;
140 }
141 TemplateInstance ti = sym.parent.isTemplateInstance();
142 if (ti && ti.toAlias() == sym)
143 buf.writestring(ti.toChars());
144 else
145 buf.writestring(sym.toChars());
146 }
147
148 Expression dotExp(Scope sc, Expression e, Identifier ident)
149 {
150 uint offset;
151
152 VarDeclaration v;
153 Dsymbol s;
154 DotVarExp de;
155 Declaration d;
156
157 version (LOGDOTEXP) {
158 printf("TypeStruct.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
159 }
160 if (!sym.members)
161 {
162 error(e.loc, "struct %s is forward referenced", sym.toChars());
163 return new ErrorExp();
164 }
165
166 /* If e.tupleof
167 */
168 if (ident is Id.tupleof_)
169 {
170 /* Create a TupleExp out of the fields of the struct e:
171 * (e.field0, e.field1, e.field2, ...)
172 */
173 e = e.semantic(sc); // do this before turning on noaccesscheck
174 Expressions exps = new Expressions;
175 exps.reserve(sym.fields.dim);
176 for (size_t i = 0; i < sym.fields.dim; i++)
177 {
178 VarDeclaration v2 = cast(VarDeclaration)sym.fields.data[i];
179 Expression fe = new DotVarExp(e.loc, e, v2);
180 exps.push(cast(void*)fe);
181 }
182 e = new TupleExp(e.loc, exps);
183 sc = sc.push();
184 sc.noaccesscheck = 1;
185 e = e.semantic(sc);
186 sc.pop();
187 return e;
188 }
189
190 if (e.op == TOK.TOKdotexp)
191 {
192 DotExp de2 = cast(DotExp)e;
193
194 if (de2.e1.op == TOK.TOKimport)
195 {
196 assert(0); // cannot find a case where this happens; leave
197 // assert in until we do
198 ScopeExp se = cast(ScopeExp)de2.e1;
199
200 s = se.sds.search(e.loc, ident, 0);
201 e = de2.e1;
202 goto L1;
203 }
204 }
205
206 s = sym.search(e.loc, ident, 0);
207 L1:
208 if (!s)
209 {
210 if (ident !is Id.__sizeof &&
211 ident !is Id.alignof_ &&
212 ident !is Id.init_ &&
213 ident !is Id.mangleof_ &&
214 ident !is Id.stringof_ &&
215 ident !is Id.offsetof)
216 {
217 /* See if we should forward to the alias this.
218 */
219 if (sym.aliasthis)
220 {
221 /* Rewrite e.ident as:
222 * e.aliasthis.ident
223 */
224 e = new DotIdExp(e.loc, e, sym.aliasthis.ident);
225 e = new DotIdExp(e.loc, e, ident);
226 return e.semantic(sc);
227 }
228
229 /* Look for overloaded opDot() to see if we should forward request
230 * to it.
231 */
232 Dsymbol fd = search_function(sym, Id.opDot);
233 if (fd)
234 {
235 /* Rewrite e.ident as:
236 * e.opId().ident
237 */
238 e = build_overload(e.loc, sc, e, null, fd.ident);
239 e = new DotIdExp(e.loc, e, ident);
240 return e.semantic(sc);
241 }
242 }
243
244 return Type.dotExp(sc, e, ident);
245 }
246
247 if (!s.isFuncDeclaration()) // because of overloading
248 s.checkDeprecated(e.loc, sc);
249
250 s = s.toAlias();
251
252 v = s.isVarDeclaration();
253 if (v && !v.isDataseg())
254 {
255 Expression ei = v.getConstInitializer();
256 if (ei)
257 {
258 e = ei.copy(); // need to copy it if it's a StringExp
259 e = e.semantic(sc);
260 return e;
261 }
262 }
263
264 if (s.getType())
265 {
266 //return new DotTypeExp(e.loc, e, s);
267 return new TypeExp(e.loc, s.getType());
268 }
269
270 EnumMember em = s.isEnumMember();
271 if (em)
272 {
273 assert(em.value);
274 return em.value.copy();
275 }
276
277 TemplateMixin tm = s.isTemplateMixin();
278 if (tm)
279 {
280 Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, tm));
281 de2.type = e.type;
282 return de2;
283 }
284
285 TemplateDeclaration td = s.isTemplateDeclaration();
286 if (td)
287 {
288 e = new DotTemplateExp(e.loc, e, td);
289 e.semantic(sc);
290 return e;
291 }
292
293 TemplateInstance ti = s.isTemplateInstance();
294 if (ti)
295 {
296 if (!ti.semanticRun)
297 ti.semantic(sc);
298 s = ti.inst.toAlias();
299 if (!s.isTemplateInstance())
300 goto L1;
301 Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, ti));
302 de2.type = e.type;
303 return de2;
304 }
305
306 Import timp = s.isImport();
307 if (timp)
308 {
309 e = new DsymbolExp(e.loc, s, 0);
310 e = e.semantic(sc);
311 return e;
312 }
313
314 OverloadSet o = s.isOverloadSet();
315 if (o)
316 {
317 /* We really should allow this, triggered by:
318 * template c()
319 * {
320 * void a();
321 * void b () { this.a(); }
322 * }
323 * struct S
324 * {
325 * mixin c;
326 * mixin c;
327 * }
328 * alias S e;
329 */
330 error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars());
331 return new ErrorExp();
332 }
333
334 d = s.isDeclaration();
335
336 debug {
337 if (!d)
338 writef("d = %s '%s'\n", s.kind(), s.toChars());
339 }
340 assert(d);
341
342 if (e.op == TOK.TOKtype)
343 {
344 FuncDeclaration fd = sc.func;
345
346 if (d.isTupleDeclaration())
347 {
348 e = new TupleExp(e.loc, d.isTupleDeclaration());
349 e = e.semantic(sc);
350 return e;
351 }
352
353 if (d.needThis() && fd && fd.vthis)
354 {
355 e = new DotVarExp(e.loc, new ThisExp(e.loc), d);
356 e = e.semantic(sc);
357 return e;
358 }
359
360 return new VarExp(e.loc, d, 1);
361 }
362
363 if (d.isDataseg())
364 {
365 // (e, d)
366 accessCheck(e.loc, sc, e, d);
367 VarExp ve = new VarExp(e.loc, d);
368 e = new CommaExp(e.loc, e, ve);
369 e.type = d.type;
370 return e;
371 }
372
373 if (v)
374 {
375 if (v.toParent() != sym)
376 sym.error(e.loc, "'%s' is not a member", v.toChars());
377
378 // *(&e + offset)
379 accessCheck(e.loc, sc, e, d);
380 static if (false) {
381 Expression b = new AddrExp(e.loc, e);
382 b.type = e.type.pointerTo();
383 b = new AddExp(e.loc, b, new IntegerExp(e.loc, v.offset, Type.tint32));
384 b.type = v.type.pointerTo();
385 b = new PtrExp(e.loc, b);
386 b.type = v.type.addMod(e.type.mod);
387 return b;
388 }
389 }
390
391 de = new DotVarExp(e.loc, e, d);
392 return de.semantic(sc);
393 }
394
395 uint memalign(uint salign)
396 {
397 sym.size(Loc(0)); // give error for forward references
398 return sym.structalign;
399 }
400
401 Expression defaultInit(Loc loc)
402 {
403 Symbol* s;
404 Declaration d;
405
406 version (LOGDEFAULTINIT) {
407 printf("TypeStruct::defaultInit() '%s'\n", toChars());
408 }
409 s = sym.toInitializer();
410 d = new SymbolDeclaration(sym.loc, s, sym);
411 assert(d);
412 d.type = this;
413 return new VarExp(sym.loc, d);
414 }
415
416 bool isZeroInit(Loc loc)
417 {
418 return sym.zeroInit;
419 }
420
421 int isAssignable()
422 {
423 /* If any of the fields are const or invariant,
424 * then one cannot assign this struct.
425 */
426 for (size_t i = 0; i < sym.fields.dim; i++)
427 {
428 VarDeclaration v = cast(VarDeclaration)sym.fields.data[i];
429 if (v.isConst() || v.isInvariant())
430 return false;
431 }
432 return true;
433 }
434
435 bool checkBoolean()
436 {
437 return false;
438 }
439
440 dt_t** toDt(dt_t** pdt)
441 {
442 sym.toDt(pdt);
443 return pdt;
444 }
445
446 MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
447 {
448 assert(false);
449 }
450
451 TypeInfoDeclaration getTypeInfoDeclaration()
452 {
453 return new TypeInfoStructDeclaration(this);
454 }
455
456 bool hasPointers()
457 {
458 StructDeclaration s = sym;
459
460 sym.size(Loc(0)); // give error for forward references
461 for (size_t i = 0; i < s.fields.dim; i++)
462 {
463 Dsymbol sm = cast(Dsymbol)s.fields.data[i];
464 Declaration d = sm.isDeclaration();
465 if (d.storage_class & STC.STCref || d.hasPointers())
466 return true;
467 }
468
469 return false;
470 }
471
472 MATCH implicitConvTo(Type to)
473 {
474 MATCH m;
475
476 //printf("TypeStruct.implicitConvTo(%s => %s)\n", toChars(), to.toChars());
477 if (ty == to.ty && sym == (cast(TypeStruct)to).sym)
478 {
479 m = MATCHexact; // exact match
480 if (mod != to.mod)
481 {
482 if (to.mod == MODconst)
483 m = MATCHconst;
484 else
485 { /* Check all the fields. If they can all be converted,
486 * allow the conversion.
487 */
488 for (int i = 0; i < sym.fields.dim; i++)
489 {
490 Dsymbol s = cast(Dsymbol)sym.fields.data[i];
491 VarDeclaration v = s.isVarDeclaration();
492 assert(v && v.storage_class & STCfield);
493
494 // 'from' type
495 Type tvf = v.type.addMod(mod);
496
497 // 'to' type
498 Type tv = v.type.castMod(to.mod);
499
500 //printf("\t%s => %s, match = %d\n", v.type.toChars(), tv.toChars(), tvf.implicitConvTo(tv));
501 if (tvf.implicitConvTo(tv) < MATCHconst)
502 return MATCHnomatch;
503 }
504 m = MATCHconst;
505 }
506 }
507 }
508 else if (sym.aliasthis)
509 {
510 m = MATCHnomatch;
511 Declaration d = sym.aliasthis.isDeclaration();
512 if (d)
513 {
514 assert(d.type);
515 Type t = d.type.addMod(mod);
516 m = t.implicitConvTo(to);
517 }
518 }
519 else
520 m = MATCHnomatch; // no match
521 return m;
522 }
523
524 MATCH constConv(Type to)
525 {
526 if (equals(to))
527 return MATCHexact;
528 if (ty == to.ty && sym == (cast(TypeStruct)to).sym && to.mod == MODconst)
529 return MATCHconst;
530 return MATCHnomatch;
531 }
532
533 Type toHeadMutable()
534 {
535 assert(false);
536 }
537
538 version (CPP_MANGLE) {
539 void toCppMangle(OutBuffer buf, CppMangleState* cms)
540 {
541 assert(false);
542 }
543 }
544
545 type* toCtype()
546 {
547 type* t;
548 Symbol* s;
549
550 if (ctype)
551 return ctype;
552
553 //printf("TypeStruct.toCtype() '%s'\n", sym.toChars());
554 s = symbol_calloc(toStringz(sym.toPrettyChars()));
555 s.Sclass = SC.SCstruct;
556 s.Sstruct = struct_calloc();
557 s.Sstruct.Sflags |= 0; /// huh?
558 s.Sstruct.Salignsize = sym.alignsize;
559 s.Sstruct.Sstructalign = cast(ubyte)sym.structalign;
560 s.Sstruct.Sstructsize = sym.structsize;
561
562 if (sym.isUnionDeclaration())
563 s.Sstruct.Sflags |= STR.STRunion;
564
565 t = type_alloc(TYM.TYstruct);
566 t.Ttag = cast(Classsym*)s; // structure tag name
567 t.Tcount++;
568 s.Stype = t;
569 slist_add(s);
570 ctype = t;
571
572 /* Add in fields of the struct
573 * (after setting ctype to avoid infinite recursion)
574 */
575 if (global.params.symdebug) {
576 for (int i = 0; i < sym.fields.dim; i++)
577 {
578 VarDeclaration v = cast(VarDeclaration)sym.fields.data[i];
579
580 Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype());
581 s2.Smemoff = v.offset;
582 list_append(&s.Sstruct.Sfldlst, s2);
583 }
584 }
585
586 //printf("t = %p, Tflags = x%x\n", t, t.Tflags);
587 return t;
588 }
589 }