Mercurial > projects > ddmd
annotate dmd/TypeClass.d @ 187:b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
author | Abscissa |
---|---|
date | Tue, 07 Jun 2011 23:37:34 -0400 |
parents | e3afd1303184 |
children |
rev | line source |
---|---|
0 | 1 module dmd.TypeClass; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Type; |
5 import dmd.ClassDeclaration; | |
64 | 6 import dmd.TypeInstance; |
0 | 7 import dmd.Loc; |
8 import dmd.Dsymbol; | |
9 import dmd.Scope; | |
10 import dmd.OutBuffer; | |
11 import dmd.HdrGenState; | |
12 import dmd.Expression; | |
13 import dmd.Identifier; | |
14 import dmd.MATCH; | |
64 | 15 import dmd.DYNCAST; |
0 | 16 import dmd.CppMangleState; |
17 import dmd.ArrayTypes; | |
18 import dmd.TypeInfoDeclaration; | |
19 import dmd.TY; | |
20 import dmd.MOD; | |
21 import dmd.Global; | |
22 import dmd.TypePointer; | |
23 import dmd.Declaration; | |
24 import dmd.VarDeclaration; | |
25 import dmd.TOK; | |
26 import dmd.DotExp; | |
27 import dmd.Id; | |
28 import dmd.ScopeExp; | |
29 import dmd.DotVarExp; | |
30 import dmd.VarExp; | |
31 import dmd.PtrExp; | |
32 import dmd.AddExp; | |
33 import dmd.IntegerExp; | |
34 import dmd.DotIdExp; | |
35 import dmd.EnumMember; | |
36 import dmd.TemplateMixin; | |
37 import dmd.TemplateDeclaration; | |
38 import dmd.TemplateInstance; | |
39 import dmd.OverloadSet; | |
40 import dmd.DotTypeExp; | |
41 import dmd.TupleExp; | |
42 import dmd.ClassInfoDeclaration; | |
43 import dmd.TypeInfoInterfaceDeclaration; | |
44 import dmd.TypeInfoClassDeclaration; | |
45 import dmd.Util; | |
46 import dmd.NullExp; | |
47 import dmd.TypeExp; | |
48 import dmd.DotTemplateExp; | |
49 import dmd.ErrorExp; | |
50 import dmd.ThisExp; | |
51 import dmd.CommaExp; | |
52 | |
53 import dmd.expression.Util; | |
54 import dmd.backend.Symbol; | |
55 import dmd.backend.TYPE; | |
56 import dmd.backend.Util; | |
57 import dmd.backend.SC; | |
58 import dmd.backend.STR; | |
59 import dmd.backend.TYM; | |
60 import dmd.backend.LIST; | |
61 import dmd.backend.Classsym; | |
62 | |
63 import std.string : toStringz; | |
64 | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
65 import dmd.DDMDExtensions; |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
66 |
0 | 67 class TypeClass : Type |
68 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
69 mixin insertMemberExtension!(typeof(this)); |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
70 |
0 | 71 ClassDeclaration sym; |
72 | |
73 this(ClassDeclaration sym) | |
74 { | |
178 | 75 register(); |
0 | 76 super(TY.Tclass); |
77 this.sym = sym; | |
78 } | |
79 | |
72 | 80 override ulong size(Loc loc) |
0 | 81 { |
82 return PTRSIZE; | |
83 } | |
84 | |
72 | 85 override string toChars() |
0 | 86 { |
87 if (mod) | |
88 return Type.toChars(); | |
89 return sym.toPrettyChars(); | |
90 } | |
91 | |
72 | 92 override Type syntaxCopy() |
0 | 93 { |
94 assert(false); | |
95 } | |
96 | |
72 | 97 override Type semantic(Loc loc, Scope sc) |
0 | 98 { |
99 //printf("TypeClass.semantic(%s)\n", sym.toChars()); | |
100 if (deco) | |
101 return this; | |
102 //printf("\t%s\n", merge().deco); | |
103 return merge(); | |
104 } | |
105 | |
72 | 106 override Dsymbol toDsymbol(Scope sc) |
0 | 107 { |
108 return sym; | |
109 } | |
110 | |
72 | 111 override void toDecoBuffer(OutBuffer buf, int flag) |
0 | 112 { |
113 string name = sym.mangle(); | |
114 //printf("TypeClass.toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name); | |
115 Type.toDecoBuffer(buf, flag); | |
116 buf.printf("%s", name); | |
117 } | |
118 | |
72 | 119 override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) |
0 | 120 { |
121 if (mod != this.mod) | |
122 { | |
123 toCBuffer3(buf, hgs, mod); | |
124 return; | |
125 } | |
126 buf.writestring(sym.toChars()); | |
127 } | |
128 | |
72 | 129 override Expression dotExp(Scope sc, Expression e, Identifier ident) |
0 | 130 { |
131 uint offset; | |
132 | |
133 Expression b; | |
134 VarDeclaration v; | |
135 Dsymbol s; | |
136 | |
137 version (LOGDOTEXP) { | |
138 printf("TypeClass.dotExp(e='%s', ident='%s')\n", e.toChars(), ident.toChars()); | |
139 } | |
140 | |
141 if (e.op == TOK.TOKdotexp) | |
142 { | |
143 DotExp de = cast(DotExp)e; | |
144 | |
145 if (de.e1.op == TOK.TOKimport) | |
146 { | |
147 ScopeExp se = cast(ScopeExp)de.e1; | |
148 | |
149 s = se.sds.search(e.loc, ident, 0); | |
150 e = de.e1; | |
151 goto L1; | |
152 } | |
153 } | |
154 | |
155 if (ident is Id.tupleof_) | |
156 { | |
157 /* Create a TupleExp | |
158 */ | |
159 e = e.semantic(sc); // do this before turning on noaccesscheck | |
160 Expressions exps = new Expressions; | |
161 exps.reserve(sym.fields.dim); | |
162 for (size_t i = 0; i < sym.fields.dim; i++) | |
163 { | |
79 | 164 VarDeclaration v2 = cast(VarDeclaration)sym.fields[i]; |
0 | 165 Expression fe = new DotVarExp(e.loc, e, v2); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
166 exps.push(fe); |
0 | 167 } |
168 e = new TupleExp(e.loc, exps); | |
169 sc = sc.push(); | |
170 sc.noaccesscheck = 1; | |
171 e = e.semantic(sc); | |
172 sc.pop(); | |
173 return e; | |
174 } | |
175 | |
176 s = sym.search(e.loc, ident, 0); | |
177 L1: | |
178 if (!s) | |
179 { | |
180 // See if it's a base class | |
181 ClassDeclaration cbase; | |
182 for (cbase = sym.baseClass; cbase; cbase = cbase.baseClass) | |
183 { | |
184 if (cbase.ident.equals(ident)) | |
185 { | |
186 e = new DotTypeExp(Loc(0), e, cbase); | |
187 return e; | |
188 } | |
189 } | |
190 | |
191 if (ident is Id.classinfo_) | |
192 { | |
166
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
135
diff
changeset
|
193 assert(global.classinfo); |
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
135
diff
changeset
|
194 Type t = global.classinfo.type; |
0 | 195 if (e.op == TOK.TOKtype || e.op == TOK.TOKdottype) |
196 { | |
197 /* For type.classinfo, we know the classinfo | |
198 * at compile time. | |
199 */ | |
200 if (!sym.vclassinfo) | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
201 sym.vclassinfo = new TypeInfoClassDeclaration(sym.type); |
0 | 202 |
203 e = new VarExp(e.loc, sym.vclassinfo); | |
204 e = e.addressOf(sc); | |
205 e.type = t; // do this so we don't get redundant dereference | |
206 } | |
207 else | |
208 { | |
209 /* For class objects, the classinfo reference is the first | |
210 * entry in the vtbl[] | |
211 */ | |
212 e = new PtrExp(e.loc, e); | |
213 e.type = t.pointerTo(); | |
214 if (sym.isInterfaceDeclaration()) | |
215 { | |
216 if (sym.isCPPinterface()) | |
217 { | |
218 /* C++ interface vtbl[]s are different in that the | |
219 * first entry is always pointer to the first virtual | |
220 * function, not classinfo. | |
221 * We can't get a .classinfo for it. | |
222 */ | |
223 error(e.loc, "no .classinfo for C++ interface objects"); | |
224 } | |
225 /* For an interface, the first entry in the vtbl[] | |
226 * is actually a pointer to an instance of struct Interface. | |
227 * The first member of Interface is the .classinfo, | |
228 * so add an extra pointer indirection. | |
229 */ | |
230 e.type = e.type.pointerTo(); | |
231 e = new PtrExp(e.loc, e); | |
232 e.type = t.pointerTo(); | |
233 } | |
234 e = new PtrExp(e.loc, e, t); | |
235 } | |
236 return e; | |
237 } | |
238 | |
239 if (ident is Id.__vptr) | |
240 { | |
241 /* The pointer to the vtbl[] | |
242 * *cast(invariant(void*)**)e | |
243 */ | |
176 | 244 e = e.castTo(sc, global.tvoidptr.invariantOf().pointerTo().pointerTo()); |
0 | 245 e = new PtrExp(e.loc, e); |
246 e = e.semantic(sc); | |
247 return e; | |
248 } | |
249 | |
250 if (ident is Id.__monitor) | |
251 { /* The handle to the monitor (call it a void*) | |
252 * *(cast(void**)e + 1) | |
253 */ | |
176 | 254 e = e.castTo(sc, global.tvoidptr.pointerTo()); |
0 | 255 e = new AddExp(e.loc, e, new IntegerExp(1)); |
256 e = new PtrExp(e.loc, e); | |
257 e = e.semantic(sc); | |
258 return e; | |
259 } | |
260 | |
261 if (ident is Id.typeinfo_) | |
262 { | |
263 if (!global.params.useDeprecated) | |
264 error(e.loc, ".typeinfo deprecated, use typeid(type)"); | |
265 | |
266 return getTypeInfo(sc); | |
267 } | |
268 if (ident is Id.outer && sym.vthis) | |
269 { | |
270 s = sym.vthis; | |
271 } | |
272 else | |
273 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
274 return noMember(sc, e, ident); |
0 | 275 } |
276 } | |
277 | |
278 if (!s.isFuncDeclaration()) // because of overloading | |
279 s.checkDeprecated(e.loc, sc); | |
280 | |
281 s = s.toAlias(); | |
282 v = s.isVarDeclaration(); | |
283 | |
284 if (v && !v.isDataseg()) | |
285 { | |
286 Expression ei = v.getConstInitializer(); | |
287 | |
288 if (ei) | |
289 { | |
290 e = ei.copy(); // need to copy it if it's a StringExp | |
291 e = e.semantic(sc); | |
292 return e; | |
293 } | |
294 } | |
295 | |
296 if (s.getType()) | |
297 { | |
298 // if (e.op == TOKtype) | |
299 return new TypeExp(e.loc, s.getType()); | |
300 // return new DotTypeExp(e.loc, e, s); | |
301 } | |
302 | |
303 EnumMember em = s.isEnumMember(); | |
304 if (em) | |
305 { | |
306 assert(em.value); | |
307 return em.value.copy(); | |
308 } | |
309 | |
310 TemplateMixin tm = s.isTemplateMixin(); | |
311 if (tm) | |
312 { | |
313 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); | |
314 de.type = e.type; | |
315 return de; | |
316 } | |
317 | |
318 TemplateDeclaration td = s.isTemplateDeclaration(); | |
319 if (td) | |
320 { | |
321 e = new DotTemplateExp(e.loc, e, td); | |
322 e.semantic(sc); | |
323 return e; | |
324 } | |
325 | |
326 TemplateInstance ti = s.isTemplateInstance(); | |
327 if (ti) | |
328 { | |
329 if (!ti.semanticRun) | |
330 ti.semantic(sc); | |
331 s = ti.inst.toAlias(); | |
332 if (!s.isTemplateInstance()) | |
333 goto L1; | |
334 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); | |
335 de.type = e.type; | |
336 return de; | |
337 } | |
338 | |
339 OverloadSet o = s.isOverloadSet(); | |
340 if (o) | |
341 { | |
342 /* We really should allow this | |
343 */ | |
344 error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars()); | |
345 return new ErrorExp(); | |
346 } | |
347 | |
348 Declaration d = s.isDeclaration(); | |
349 if (!d) | |
350 { | |
351 e.error("%s.%s is not a declaration", e.toChars(), ident.toChars()); | |
352 return new ErrorExp(); | |
353 } | |
354 | |
355 if (e.op == TOK.TOKtype) | |
356 { | |
357 /* It's: | |
358 * Class.d | |
359 */ | |
360 if (d.isTupleDeclaration()) | |
361 { | |
362 e = new TupleExp(e.loc, d.isTupleDeclaration()); | |
363 e = e.semantic(sc); | |
364 return e; | |
365 } | |
73 | 366 else if (d.needThis() && (hasThis(sc) || !(sc.intypeof || d.isFuncDeclaration()))) |
0 | 367 { |
368 if (sc.func) | |
369 { | |
370 ClassDeclaration thiscd; | |
371 thiscd = sc.func.toParent().isClassDeclaration(); | |
372 | |
373 if (thiscd) | |
374 { | |
375 ClassDeclaration cd = e.type.isClassHandle(); | |
376 | |
377 if (cd is thiscd) | |
378 { | |
379 e = new ThisExp(e.loc); | |
380 e = new DotTypeExp(e.loc, e, cd); | |
381 DotVarExp de = new DotVarExp(e.loc, e, d); | |
382 e = de.semantic(sc); | |
383 return e; | |
384 } | |
385 else if ((!cd || !cd.isBaseOf(thiscd, null)) && !d.isFuncDeclaration()) | |
386 e.error("'this' is required, but %s is not a base class of %s", e.type.toChars(), thiscd.toChars()); | |
387 } | |
388 } | |
389 | |
390 /* Rewrite as: | |
391 * this.d | |
392 */ | |
393 DotVarExp de = new DotVarExp(e.loc, new ThisExp(e.loc), d); | |
394 e = de.semantic(sc); | |
395 return e; | |
396 } | |
397 else | |
398 { | |
399 VarExp ve = new VarExp(e.loc, d, 1); | |
400 return ve; | |
401 } | |
402 } | |
403 | |
404 if (d.isDataseg()) | |
405 { | |
406 // (e, d) | |
407 accessCheck(e.loc, sc, e, d); | |
408 VarExp ve = new VarExp(e.loc, d); | |
409 e = new CommaExp(e.loc, e, ve); | |
410 e.type = d.type; | |
411 return e; | |
412 } | |
413 | |
414 if (d.parent && d.toParent().isModule()) | |
415 { | |
416 // (e, d) | |
417 VarExp ve = new VarExp(e.loc, d, 1); | |
418 e = new CommaExp(e.loc, e, ve); | |
419 e.type = d.type; | |
420 return e; | |
421 } | |
422 | |
423 DotVarExp de = new DotVarExp(e.loc, e, d); | |
424 return de.semantic(sc); | |
425 } | |
426 | |
72 | 427 override ClassDeclaration isClassHandle() |
0 | 428 { |
429 return sym; | |
430 } | |
431 | |
72 | 432 override bool isBaseOf(Type t, int* poffset) |
0 | 433 { |
56 | 434 if (t.ty == Tclass) |
435 { | |
436 ClassDeclaration cd; | |
437 | |
438 cd = (cast(TypeClass)t).sym; | |
439 if (sym.isBaseOf(cd, poffset)) | |
440 return true; | |
441 } | |
442 | |
443 return false; | |
0 | 444 } |
445 | |
72 | 446 override MATCH implicitConvTo(Type to) |
0 | 447 { |
448 //printf("TypeClass.implicitConvTo(to = '%s') %s\n", to.toChars(), toChars()); | |
449 MATCH m = constConv(to); | |
450 if (m != MATCH.MATCHnomatch) | |
451 return m; | |
452 | |
453 ClassDeclaration cdto = to.isClassHandle(); | |
454 if (cdto && cdto.isBaseOf(sym, null)) | |
455 { | |
456 //printf("'to' is base\n"); | |
457 return MATCH.MATCHconvert; | |
458 } | |
459 | |
460 if (global.params.Dversion == 1) | |
461 { | |
462 // Allow conversion to (void *) | |
463 if (to.ty == TY.Tpointer && (cast(TypePointer)to).next.ty == TY.Tvoid) | |
464 return MATCH.MATCHconvert; | |
465 } | |
466 | |
467 m = MATCH.MATCHnomatch; | |
468 if (sym.aliasthis) | |
469 { | |
470 Declaration d = sym.aliasthis.isDeclaration(); | |
471 if (d) | |
472 { | |
473 assert(d.type); | |
474 Type t = d.type.addMod(mod); | |
475 m = t.implicitConvTo(to); | |
476 } | |
477 } | |
478 | |
479 return m; | |
480 } | |
481 | |
72 | 482 override Expression defaultInit(Loc loc) |
0 | 483 { |
484 version (LOGDEFAULTINIT) { | |
485 printf("TypeClass::defaultInit() '%s'\n", toChars()); | |
486 } | |
135 | 487 return new NullExp(loc, this); |
0 | 488 } |
489 | |
72 | 490 override bool isZeroInit(Loc loc) |
0 | 491 { |
492 return true; | |
493 } | |
494 | |
72 | 495 override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) |
0 | 496 { |
64 | 497 //printf("TypeClass.deduceType(this = %s)\n", toChars()); |
498 | |
499 /* If this class is a template class, and we're matching | |
500 * it against a template instance, convert the class type | |
501 * to a template instance, too, and try again. | |
502 */ | |
503 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
504 | |
505 if (tparam && tparam.ty == Tinstance) | |
506 { | |
507 if (ti && ti.toAlias() == sym) | |
508 { | |
509 TypeInstance t = new TypeInstance(Loc(0), ti); | |
510 return t.deduceType(sc, tparam, parameters, dedtypes); | |
511 } | |
512 | |
513 /* Match things like: | |
514 * S!(T).foo | |
515 */ | |
516 TypeInstance tpi = cast(TypeInstance)tparam; | |
517 if (tpi.idents.dim) | |
518 { Identifier id = cast(Identifier)tpi.idents.data[tpi.idents.dim - 1]; | |
519 if (id.dyncast() == DYNCAST.DYNCAST_IDENTIFIER && sym.ident.equals(id)) | |
520 { | |
521 Type tparent = sym.parent.getType(); | |
522 if (tparent) | |
523 { | |
524 /* Slice off the .foo in S!(T).foo | |
525 */ | |
526 tpi.idents.dim--; | |
527 MATCH m = tparent.deduceType(sc, tpi, parameters, dedtypes); | |
528 tpi.idents.dim++; | |
529 return m; | |
530 } | |
531 } | |
532 } | |
533 } | |
534 | |
535 // Extra check | |
536 if (tparam && tparam.ty == Tclass) | |
537 { | |
538 TypeClass tp = cast(TypeClass)tparam; | |
539 | |
540 //printf("\t%d\n", (MATCH) implicitConvTo(tp)); | |
541 return implicitConvTo(tp); | |
542 } | |
543 return Type.deduceType(sc, tparam, parameters, dedtypes); | |
0 | 544 } |
545 | |
72 | 546 override bool isauto() |
0 | 547 { |
548 return sym.isauto; | |
549 } | |
550 | |
72 | 551 override bool checkBoolean() |
0 | 552 { |
553 return true; | |
554 } | |
555 | |
72 | 556 override TypeInfoDeclaration getTypeInfoDeclaration() |
0 | 557 { |
558 if (sym.isInterfaceDeclaration()) | |
559 return new TypeInfoInterfaceDeclaration(this); | |
560 else | |
561 return new TypeInfoClassDeclaration(this); | |
562 } | |
563 | |
72 | 564 override bool hasPointers() |
0 | 565 { |
566 return true; | |
567 } | |
568 | |
72 | 569 override bool builtinTypeInfo() |
0 | 570 { |
571 /* This is statically put out with the ClassInfo, so | |
572 * claim it is built in so it isn't regenerated by each module. | |
573 */ | |
574 version (DMDV2) { | |
575 return mod ? false : true; | |
576 } else { | |
577 return true; | |
578 } | |
579 } | |
580 | |
581 version (DMDV2) { | |
72 | 582 override Type toHeadMutable() |
0 | 583 { |
584 assert(false); | |
585 } | |
586 | |
72 | 587 override MATCH constConv(Type to) |
0 | 588 { |
589 if (equals(to)) | |
590 return MATCH.MATCHexact; | |
591 | |
592 if (ty == to.ty && sym == (cast(TypeClass)to).sym && to.mod == MOD.MODconst) | |
593 return MATCH.MATCHconst; | |
594 | |
595 return MATCH.MATCHnomatch; | |
596 } | |
597 | |
598 version (CPP_MANGLE) { | |
599 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
600 { | |
601 assert(false); | |
602 } | |
603 } | |
604 } | |
605 | |
72 | 606 override type* toCtype() |
0 | 607 { |
608 type* t; | |
609 Symbol* s; | |
610 | |
611 //printf("TypeClass.toCtype() %s\n", toChars()); | |
612 if (ctype) | |
613 return ctype; | |
614 | |
615 /* Need this symbol to do C++ name mangling | |
616 */ | |
617 string name = sym.isCPPinterface() ? sym.ident.toChars() : sym.toPrettyChars(); | |
618 s = symbol_calloc(toStringz(name)); | |
619 s.Sclass = SC.SCstruct; | |
620 s.Sstruct = struct_calloc(); | |
621 s.Sstruct.Sflags |= STR.STRclass; | |
622 s.Sstruct.Salignsize = sym.alignsize; | |
623 s.Sstruct.Sstructalign = cast(ubyte)sym.structalign; | |
624 s.Sstruct.Sstructsize = sym.structsize; | |
625 | |
626 t = type_alloc(TYM.TYstruct); | |
627 t.Ttag = cast(Classsym*)s; // structure tag name | |
628 t.Tcount++; | |
629 s.Stype = t; | |
630 slist_add(s); | |
631 | |
632 t = type_allocn(TYM.TYnptr, t); | |
633 | |
634 t.Tcount++; | |
635 ctype = t; | |
636 | |
637 /* Add in fields of the class | |
638 * (after setting ctype to avoid infinite recursion) | |
639 */ | |
640 if (global.params.symdebug) | |
641 for (int i = 0; i < sym.fields.dim; i++) | |
642 { | |
79 | 643 VarDeclaration v = cast(VarDeclaration)sym.fields[i]; |
0 | 644 |
645 Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype()); | |
646 s2.Smemoff = v.offset; | |
647 list_append(&s.Sstruct.Sfldlst, s2); | |
648 } | |
649 | |
650 return t; | |
651 } | |
652 | |
72 | 653 override Symbol* toSymbol() |
0 | 654 { |
655 return sym.toSymbol(); | |
656 } | |
72 | 657 } |