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