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