Rune - Clean up strings
[rune.git] / librune / type.c
1 /*
2  * TYPE.C
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9
10 Type DynamicLValueType;
11 Type DynamicRValueType;
12
13 Type NumericType;       /* generic numeric placeholder */
14 Type IntegralType;      /* generic integral placeholder */
15 Type SIntegerType;      /* generic signed integer placeholder */
16 Type UIntegerType;      /* generic unsigned integer placeholder */
17
18 Type VoidType;
19 Type BoolType;
20 Type Int8Type;
21 Type UInt8Type;
22 Type Int16Type;
23 Type UInt16Type;
24 Type Int32Type;
25 Type UInt32Type;
26 Type Int64Type;
27 Type UInt64Type;
28 Type Int128Type;
29 Type UInt128Type;
30
31 Type IntPtrType;
32 Type UIntPtrType;
33 Type OffType;
34 Type SizeType;
35
36 Type FloatType;         /* generic float placeholder */
37 Type Float32Type;
38 Type Float64Type;
39 Type Float128Type;
40
41 Type PointerType;       /* generic pointer placeholder */
42 Type CCharType;         /* const uchar          */
43 Type StrType;           /* const uchar *        */
44 Type UCharPtrType;      /* uchar *              */
45 Type UCharPtrPtrType;   /* uchar **             */
46 Type CUCharPtrPtrType;  /* const uchar **       */
47 Type VoidPtrType;       /* void *               */
48 Type VoidRefType;       /* void @               */
49 Type CVoidPtrType;      /* const void *         */
50 Type LVoidPtrType;      /* lvalue void *        */
51
52 Type LexRefType;        /* run-time access class tie-ins */
53 Type ScopeType;
54 Type DeclarationType;
55 Type SemGroupType;
56 Type PointerInfoType;
57 Type TypeType;
58 Type FILLERTypeType;
59 Type FILLERDeclType;
60
61 typelist_t DynamicTypeList = RUNE_HEAD_INITIALIZER(DynamicTypeList);
62 typelist_t CompoundTypeList = RUNE_HEAD_INITIALIZER(CompoundTypeList);
63 typelist_t ArgsTypeList = RUNE_HEAD_INITIALIZER(ArgsTypeList);
64 typelist_t StorageTypeList = RUNE_HEAD_INITIALIZER(StorageTypeList);
65
66 static void initInternalClassType(Type *type, Declaration *d);
67
68 Type *BaseTypeAry[] = {
69                 &DynamicLValueType, &DynamicRValueType, &NumericType,
70                 &IntegralType, &SIntegerType, &UIntegerType,
71                 &VoidType, &BoolType, &Int8Type, &UInt8Type,
72                 &Int16Type, &UInt16Type, &Int32Type, &UInt32Type,
73                 &Int64Type, &UInt64Type, &Int128Type, &UInt128Type,
74
75                 &IntPtrType, &UIntPtrType, &OffType, &SizeType,
76
77                 &FloatType, &Float32Type, &Float64Type, &Float128Type,
78
79                 &PointerType, &CCharType, &StrType, &UCharPtrType,
80                 &UCharPtrPtrType, &CUCharPtrPtrType,
81                 &VoidPtrType, &VoidRefType, &CVoidPtrType,
82                 &LVoidPtrType,
83
84                 &LexRefType, &ScopeType, &DeclarationType, &SemGroupType,
85                 &PointerInfoType, &TypeType,
86                 &FILLERTypeType, &FILLERDeclType,
87                 NULL
88 };
89
90 void
91 initType(Type *type, typelist_t *list, int op)
92 {
93         type->ty_Op = op;
94         RUNE_INIT(&type->ty_QList);
95         if (list)
96                 RUNE_INSERT_TAIL(list, type, ty_Node);
97         type->ty_SQList = list;
98         type->ty_Info.in_Type = type;
99         type->ty_Info.in_Refs = PINFO_STATIC;
100 }
101
102 void
103 initQualType(Type *type, typelist_t *list, int op, int sqflags)
104 {
105         initType(type, list, op);
106         type->ty_SQFlags = sqflags;
107 }
108
109 void
110 initPtrType(Type *type, Type *ptrto, int sqflags)
111 {
112         initQualType(type, &ptrto->ty_QList, TY_PTRTO, sqflags);
113         type->ty_PtrType.et_Type = ptrto;
114         /*type->ty_Bytes = sizeof(PointerStor);*/
115         type->ty_AlignMask = POINTERSTOR_ALIGN;
116 }
117
118 void
119 initCPtrType(Type *type, Type *ptrto, int sqflags)
120 {
121         initQualType(type, &ptrto->ty_QList, TY_CPTRTO, sqflags);
122         type->ty_PtrType.et_Type = ptrto;
123         /*type->ty_Bytes = sizeof(void *);*/
124         type->ty_AlignMask = sizeof(void *) - 1;
125 }
126
127 static void
128 initRefType(Type *type, Type *refto, int sqflags)
129 {
130         initQualType(type, &refto->ty_QList, TY_REFTO, sqflags);
131         type->ty_RefType.et_Type = refto;
132         /*type->ty_Bytes = sizeof(PointerStor);*/
133         type->ty_AlignMask = POINTERSTOR_ALIGN;
134 }
135
136 void
137 TypeInit(void)
138 {
139         int i;
140
141         initQualType(&DynamicLValueType, &DynamicTypeList,
142                      TY_DYNAMIC, SF_LVALUE);
143         initType(&DynamicRValueType, &DynamicTypeList, TY_DYNAMIC);
144         initType(&NumericType, NULL, TY_UNRESOLVED);
145         initType(&IntegralType, NULL, TY_UNRESOLVED);
146         initType(&SIntegerType, NULL, TY_UNRESOLVED);
147         initType(&UIntegerType, NULL, TY_UNRESOLVED);
148         initType(&FloatType, NULL, TY_UNRESOLVED);
149         initType(&PointerType, NULL, TY_UNRESOLVED);
150         PointerType.ty_AlignMask = POINTERSTOR_ALIGN;
151
152         initType(&VoidType, NULL, TY_UNRESOLVED);
153         initType(&BoolType, NULL, TY_UNRESOLVED);
154         initType(&Int8Type, NULL, TY_UNRESOLVED);
155         initType(&UInt8Type, NULL, TY_UNRESOLVED);
156         initType(&Int16Type, NULL, TY_UNRESOLVED);
157         initType(&UInt16Type, NULL, TY_UNRESOLVED);
158         initType(&Int32Type, NULL, TY_UNRESOLVED);
159         initType(&UInt32Type, NULL, TY_UNRESOLVED);
160         initType(&Int64Type, NULL, TY_UNRESOLVED);
161         initType(&UInt64Type, NULL, TY_UNRESOLVED);
162
163         initType(&IntPtrType, NULL, TY_UNRESOLVED);
164         initType(&UIntPtrType, NULL, TY_UNRESOLVED);
165         initType(&OffType, NULL, TY_UNRESOLVED);
166         initType(&SizeType, NULL, TY_UNRESOLVED);
167
168         initType(&Float32Type, NULL, TY_UNRESOLVED);
169         initType(&Float64Type, NULL, TY_UNRESOLVED);
170         initType(&Float128Type, NULL, TY_UNRESOLVED);
171
172         initQualType(&CCharType, NULL, TY_UNRESOLVED, SF_CONST);
173         initPtrType(&StrType, &CCharType, 0);
174         initPtrType(&UCharPtrType, &UInt8Type, 0);
175         initPtrType(&UCharPtrPtrType, &UCharPtrType, 0);
176         initPtrType(&CUCharPtrPtrType, &StrType, 0);
177         initPtrType(&VoidPtrType, &VoidType, 0);
178         initRefType(&VoidRefType, &VoidType, 0);
179         initCPtrType(&CVoidPtrType, &VoidType, SF_CONST);
180         initPtrType(&LVoidPtrType, &VoidType, SF_LVALUE);
181
182         /*
183          * Mark internal types (not all are bound to classes so it is
184          * easiest to just do it here).  This will prevent the collapse
185          * code from trying to collapse our base types.
186          */
187         for (i = 0; BaseTypeAry[i]; ++i)
188                 BaseTypeAry[i]->ty_Flags |= TF_ISINTERNAL;
189
190         StrTableAlloc("void", 4, SPECIAL_INTERNAL_VOID);
191         StrTableAlloc("bool", 4, SPECIAL_INTERNAL_BOOL);
192         StrTableAlloc("int8_t", 6, SPECIAL_INTERNAL_INT8);
193         StrTableAlloc("uint8_t", 7, SPECIAL_INTERNAL_UINT8);
194         StrTableAlloc("int16_t", 7, SPECIAL_INTERNAL_INT16);
195         StrTableAlloc("uint16_t", 8, SPECIAL_INTERNAL_UINT16);
196         StrTableAlloc("int32_t", 7, SPECIAL_INTERNAL_INT32);
197         StrTableAlloc("uint32_t", 8, SPECIAL_INTERNAL_UINT32);
198         StrTableAlloc("int64_t", 7, SPECIAL_INTERNAL_INT64);
199         StrTableAlloc("uint64_t", 8, SPECIAL_INTERNAL_UINT64);
200         StrTableAlloc("int128_t", 8, SPECIAL_INTERNAL_INT128);
201         StrTableAlloc("uint128_t", 9, SPECIAL_INTERNAL_UINT128);
202
203         StrTableAlloc("float32_t", 9, SPECIAL_INTERNAL_FLOAT32);
204         StrTableAlloc("float64_t", 9, SPECIAL_INTERNAL_FLOAT64);
205         StrTableAlloc("float128_t", 10, SPECIAL_INTERNAL_FLOAT128);
206
207         StrTableAlloc("intptr_t", 8, SPECIAL_INTERNAL_INTPTR);
208         StrTableAlloc("uintptr_t", 9, SPECIAL_INTERNAL_UINTPTR);
209         StrTableAlloc("size_t", 6, SPECIAL_INTERNAL_SIZE);
210         StrTableAlloc("off_t", 5, SPECIAL_INTERNAL_OFF);
211
212         StrTableAlloc("Float", 5, SPECIAL_INTERNAL_FLOAT);
213         StrTableAlloc("Pointer", 7, SPECIAL_INTERNAL_POINTER);
214         StrTableAlloc("Numeric", 7, SPECIAL_INTERNAL_NUMERIC);
215         StrTableAlloc("Integral", 8, SPECIAL_INTERNAL_INTEGRAL);
216         StrTableAlloc("SInteger", 8, SPECIAL_INTERNAL_SINTEGER);
217         StrTableAlloc("UInteger", 8, SPECIAL_INTERNAL_UINTEGER);
218
219         StrTableAlloc("LexRef", 6, SPECIAL_INTERNAL_LEXREF);
220         StrTableAlloc("Scope", 5, SPECIAL_INTERNAL_SCOPE);
221         StrTableAlloc("Declaration", 11, SPECIAL_INTERNAL_DECLARATION);
222         StrTableAlloc("SemGroup", 8, SPECIAL_INTERNAL_SEMGROUP);
223         StrTableAlloc("PointerInfo", 11, SPECIAL_INTERNAL_POINTERINFO);
224         StrTableAlloc("Type", 4, SPECIAL_INTERNAL_TYPE);
225         StrTableAlloc("FILLERType", 10, SPECIAL_INTERNAL_FILLERTYPE);
226         StrTableAlloc("FILLERDecl", 10, SPECIAL_INTERNAL_FILLERDECL);
227
228         StrTableAlloc("__count",        7,      SPECIAL_COUNT);
229         StrTableAlloc("__data",         6,      SPECIAL_DATA);
230         StrTableAlloc("__type",         6,      SPECIAL_TYPE);
231         StrTableAlloc("__varcount",     10,     SPECIAL_VAR_COUNT);
232         StrTableAlloc("__vardata",      9,      SPECIAL_VAR_DATA);
233         StrTableAlloc("__vartype",      9,      SPECIAL_VAR_TYPE);
234         StrTableAlloc("__typeid",       8,      SPECIAL_TYPEID);
235         StrTableAlloc("__typestr",      9,      SPECIAL_TYPESTR);
236         StrTableAlloc("NULL",           4,      SPECIAL_NULL);
237 }
238
239 /*
240  * Attach an internal class, creating a global summary type for it that
241  * allows our interpreter and code generator to make various assumptions.
242  */
243 int
244 InternalClassAttach(Parse *p __unused, int t, Declaration *d)
245 {
246         Type *itype = NULL;
247         int s;
248
249         dassert_decl(d, d->d_Op == DOP_CLASS);
250
251         if ((s = StrTableSpecial(d->d_Id)) & SPECIALF_INTERNAL) {
252                 switch(s) {
253                 case SPECIAL_INTERNAL_VOID:
254                         itype = &VoidType;
255                         break;
256                 case SPECIAL_INTERNAL_BOOL:
257                         /*
258                          * Special flag helper (resolver sets TF_ISBOOL in
259                          * in the type)
260                          */
261                         itype = &BoolType;
262                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISBOOL;
263                         break;
264                 case SPECIAL_INTERNAL_INT8:
265                         itype = &Int8Type;
266                         break;
267                 case SPECIAL_INTERNAL_UINT8:
268                         itype = &UInt8Type;
269                         break;
270                 case SPECIAL_INTERNAL_INT16:
271                         itype = &Int16Type;
272                         break;
273                 case SPECIAL_INTERNAL_UINT16:
274                         itype = &UInt16Type;
275                         break;
276                 case SPECIAL_INTERNAL_INT32:
277                         itype = &Int32Type;
278                         break;
279                 case SPECIAL_INTERNAL_UINT32:
280                         itype = &UInt32Type;
281                         break;
282                 case SPECIAL_INTERNAL_INT64:
283                         itype = &Int64Type;
284                         break;
285                 case SPECIAL_INTERNAL_UINT64:
286                         itype = &UInt64Type;
287                         break;
288                 case SPECIAL_INTERNAL_INT128:
289                         itype = &Int128Type;
290                         break;
291                 case SPECIAL_INTERNAL_UINT128:
292                         itype = &UInt128Type;
293                         break;
294
295                 case SPECIAL_INTERNAL_FLOAT:
296                         /*
297                          * Special flag helper (resolver sets TF_ISFLOATING in
298                          * in the type)
299                          */
300                         itype = &FloatType;
301                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISFLOATING;
302                         break;
303                 case SPECIAL_INTERNAL_FLOAT32:
304                         itype = &Float32Type;
305                         break;
306                 case SPECIAL_INTERNAL_FLOAT64:
307                         itype = &Float64Type;
308                         break;
309                 case SPECIAL_INTERNAL_FLOAT128:
310                         itype = &Float128Type;
311                         break;
312
313                 case SPECIAL_INTERNAL_INTPTR:
314                         itype = &IntPtrType;
315                         break;
316                 case SPECIAL_INTERNAL_UINTPTR:
317                         itype = &UIntPtrType;
318                         break;
319                 case SPECIAL_INTERNAL_OFF:
320                         itype = &OffType;
321                         break;
322                 case SPECIAL_INTERNAL_SIZE:
323                         itype = &SizeType;
324                         break;
325                 /* NOTE: There is no ssize_t in rune. size_t is signed */
326
327                 case SPECIAL_INTERNAL_POINTER:
328                         itype = &PointerType;
329                         break;
330                 case SPECIAL_INTERNAL_NUMERIC:
331                         itype = &NumericType;
332                         break;
333                 case SPECIAL_INTERNAL_INTEGRAL:
334                         itype = &IntegralType;
335                         break;
336                 case SPECIAL_INTERNAL_SINTEGER:
337                         /*
338                          * Special flag helper (resolver sets TF_ISINTEGER in
339                          * in the type)
340                          */
341                         itype = &SIntegerType;
342                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISINTEGER;
343                         break;
344                 case SPECIAL_INTERNAL_UINTEGER:
345                         /*
346                          * Special flag helper (resolver sets TF_ISINTEGER
347                          * and TF_ISUNSIGNED in the type)
348                          */
349                         itype = &UIntegerType;
350                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISUNSIGNED;
351                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISINTEGER;
352                         break;
353
354                 case SPECIAL_INTERNAL_LEXREF:
355                         itype = &LexRefType;
356                         break;
357                 case SPECIAL_INTERNAL_SCOPE:
358                         itype = &ScopeType;
359                         break;
360                 case SPECIAL_INTERNAL_DECLARATION:
361                         itype = &DeclarationType;
362                         break;
363                 case SPECIAL_INTERNAL_SEMGROUP:
364                         itype = &SemGroupType;
365                         break;
366                 case SPECIAL_INTERNAL_POINTERINFO:
367                         itype = &PointerInfoType;
368                         break;
369                 case SPECIAL_INTERNAL_TYPE:
370                         itype = &TypeType;
371                         break;
372                 case SPECIAL_INTERNAL_FILLERTYPE:
373                         itype = &FILLERTypeType;
374                         break;
375                 case SPECIAL_INTERNAL_FILLERDECL:
376                         itype = &FILLERDeclType;
377                         break;
378                 default:
379                         dpanic("Unknown internal class: %s", d->d_Id);
380                         break;
381                 }
382         }
383         initInternalClassType(itype, d);
384
385         /*
386          * Fixup for const int8 pointers... we did not have
387          * a QList to put CCharType on until now.  It will
388          * wind up on the SemGroup's sg_ClassList.
389          */
390         if (itype == &UInt8Type) {
391                 TypeToQualType(itype, &CCharType,
392                                itype->ty_SQFlags | SF_CONST, NULL);
393         } 
394
395         return(t);
396 }
397
398 /*
399  * This is mostly deprecated except for official type aliases such as
400  * intptr_t.
401  */
402 int
403 InternalTypeAttach(Parse *p, int t, Declaration *d)
404 {
405         Type *itype = NULL;
406         int s;
407
408         dassert_decl(d, d->d_Op == DOP_TYPEDEF);
409
410         if ((s = StrTableSpecial(d->d_Id)) & SPECIALF_INTERNAL) {
411                 switch(s) {
412                 case SPECIAL_INTERNAL_VOID:
413                         itype = &VoidType;
414                         break;
415                 case SPECIAL_INTERNAL_BOOL:
416                         itype = &BoolType;
417                         break;
418                 case SPECIAL_INTERNAL_INT8:
419                         itype = &Int8Type;
420                         break;
421                 case SPECIAL_INTERNAL_UINT8:
422                         itype = &UInt8Type;
423                         break;
424                 case SPECIAL_INTERNAL_INT16:
425                         itype = &Int16Type;
426                         break;
427                 case SPECIAL_INTERNAL_UINT16:
428                         itype = &UInt16Type;
429                         break;
430                 case SPECIAL_INTERNAL_INT32:
431                         itype = &Int32Type;
432                         break;
433                 case SPECIAL_INTERNAL_UINT32:
434                         itype = &UInt32Type;
435                         break;
436                 case SPECIAL_INTERNAL_INT64:
437                         itype = &Int64Type;
438                         break;
439                 case SPECIAL_INTERNAL_UINT64:
440                         itype = &UInt64Type;
441                         break;
442
443                 case SPECIAL_INTERNAL_FLOAT32:
444                         itype = &Float32Type;
445                         break;
446                 case SPECIAL_INTERNAL_FLOAT64:
447                         itype = &Float64Type;
448                         break;
449                 case SPECIAL_INTERNAL_FLOAT128:
450                         itype = &Float128Type;
451                         break;
452
453                 case SPECIAL_INTERNAL_INTPTR:
454                         itype = &IntPtrType;
455                         break;
456                 case SPECIAL_INTERNAL_UINTPTR:
457                         itype = &UIntPtrType;
458                         break;
459                 case SPECIAL_INTERNAL_OFF:
460                         itype = &OffType;
461                         break;
462                 case SPECIAL_INTERNAL_SIZE:
463                         itype = &SizeType;
464                         break;
465                 /* NOTE: There is no ssize_t in rune. size_t is signed */
466
467                 case SPECIAL_INTERNAL_POINTER:
468                         itype = &PointerType;
469                         break;
470                 case SPECIAL_INTERNAL_NUMERIC:
471                         itype = &NumericType;
472                         break;
473                 case SPECIAL_INTERNAL_INTEGRAL:
474                         itype = &IntegralType;
475                         break;
476                 case SPECIAL_INTERNAL_SINTEGER:
477                         itype = &SIntegerType;
478                         break;
479                 case SPECIAL_INTERNAL_UINTEGER:
480                         itype = &UIntegerType;
481                         break;
482                 default:
483                         itype = InternalRegisteredTypeLookup(d->d_Id);
484                         if (itype == NULL)
485                                 dpanic("Unknown internal type: %s", d->d_Id);
486                         break;
487                 }
488         }
489         if (itype) {
490                 if (itype->ty_Op != TY_UNRESOLVED) {
491                         t = LexError(&p->p_Token, TOK_ERR_DUPLICATE_ATTACH);
492                 } else {
493                         Type *ntype = d->d_TypedefDecl.ed_Type;
494
495                         TypeToQualType(ntype, itype, ntype->ty_SQFlags, NULL);
496                 }
497         } else {
498                 t = LexError(&p->p_Token, TOK_ERR_UNRECOGNIZED_ATTACH);
499         }
500         return(t);
501 }
502
503 Type *
504 AllocType(typelist_t *list, int op)
505 {
506         Type *type = zalloc(sizeof(Type));
507
508         initType(type, list, op);
509         return(type);
510 }
511
512 /*
513  * May be used to generate a varargs compound type, in which case the
514  * semgroup may already be resolved.
515  *
516  * We do no matching/caching at this time and callers assume that (for
517  * making adjustments) to the underlying sg at parse-time via
518  * TypeToProcType()
519  */
520 Type *
521 AllocCompoundType(SemGroup *sg)
522 {
523         Type *type;
524
525         type = AllocType(&CompoundTypeList, TY_COMPOUND);
526         type->ty_CompType.et_SemGroup = sg;
527         dassert((sg->sg_Flags & SGF_RESOLVED) == 0);
528         return(type);
529 }
530
531 /*
532  * XXX match the compound type(s)
533  */
534 Type *
535 AllocArgsType(SemGroup *sg)
536 {
537         Type *type;
538
539         type = AllocType(&ArgsTypeList, TY_ARGS);
540         type->ty_ArgsType.et_SemGroup = sg;
541         return(type);
542 }
543
544 Type *
545 AllocStorageType(runesize_t bytes)
546 {
547         Type *type;
548
549         RUNE_FOREACH(type, &StorageTypeList, ty_Node) {
550                 if (type->ty_Op == TY_STORAGE &&
551                         type->ty_StorType.et_Bytes == bytes
552                 ) {
553                         return(type);
554                 }
555         }
556         type = AllocType(&StorageTypeList, TY_STORAGE);
557         type->ty_StorType.et_Bytes = bytes;
558         return(type);
559 }
560
561 Type *
562 AllocUnresolvedType(SemGroup *isg, SemGroup *sg, string_t *ary, int eatAry)
563 {
564         Type *type = NULL;
565
566         dassert_semgrp(sg, ary != NULL);
567
568         RUNE_FOREACH(type, &sg->sg_ClassList, ty_Node) {
569                 int i;
570
571                 if (type->ty_Op != TY_UNRESOLVED)
572                         continue;
573                 if (type->ty_UnresType.et_ImportSemGroup != isg)
574                         continue;
575
576                 for (i = 0; ary[i]; ++i) {
577                         if (ary[i] != type->ty_UnresType.et_DottedId[i])
578                                 break;
579                 }
580                 if (ary[i] == NULL &&
581                     type->ty_UnresType.et_DottedId[i] == NULL) {
582                         if (eatAry)
583                                 FreeDotIdAry(ary);
584                         return(type);
585                 }
586         }
587         type = AllocType((sg ? &sg->sg_ClassList : NULL), TY_UNRESOLVED);
588         type->ty_UnresType.et_DottedId = ary;
589         type->ty_UnresType.et_SemGroup = sg;            /* may be NULL */
590         type->ty_UnresType.et_ImportSemGroup = isg;     /* may be NULL */
591         return(type);
592 }
593
594 /*
595  * AllocClassType() - allocate a type representing a the semgroup which
596  *                      in turn represents (typically) a class.
597  */
598 Type *
599 AllocClassType(typelist_t *list, Type *super, SemGroup *sg, int visibility)
600 {
601         Type *type;
602
603         dassert(sg != NULL);
604         list = &sg->sg_ClassList;
605
606         RUNE_FOREACH(type, list, ty_Node) {
607                 if (type->ty_Op == TY_CLASS &&
608                     type->ty_ClassType.et_SemGroup == sg &&
609                     type->ty_ClassType.et_Super == super &&
610                     type->ty_Visibility == visibility
611                 ) {
612                         return(type);
613                 }
614         }
615         if (sg)
616                 dassert(&sg->sg_ClassList == list);
617         type = AllocType(list, TY_CLASS);
618         type->ty_ClassType.et_SemGroup = sg;
619         type->ty_ClassType.et_Super = super;
620         type->ty_Visibility = visibility;
621         return(type);
622 }
623
624 static
625 void
626 initInternalClassType(Type *type, Declaration *d)
627 {
628         SemGroup *sg = d->d_ClassDecl.ed_SemGroup;
629
630         initType(type, &sg->sg_ClassList, TY_CLASS);
631         RUNE_REMOVE(&sg->sg_ClassList, type, ty_Node);
632         RUNE_INSERT_HEAD(&sg->sg_ClassList, type, ty_Node);
633         type->ty_ClassType.et_SemGroup = d->d_ClassDecl.ed_SemGroup;
634         type->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
635         type->ty_Visibility = d->d_ScopeFlags & SCOPE_ALL_VISIBLE;
636         type->ty_Flags |= TF_ISINTERNAL;
637 }
638
639 Type *
640 AllocImportType(typelist_t *list, SemGroup *sg, int visibility)
641 {
642         Type *type = AllocType(list, TY_IMPORT);
643
644         type->ty_ImportType.et_SemGroup = sg;
645         type->ty_Visibility = visibility;
646         return(type);
647 }
648
649 /*
650  * adjtype must be moved to type's QList because type is being modified
651  * such that that is where it is expected to be.
652  */
653 Type *
654 TypeAdjustQList(Type *type, Type *adjtype)
655 {
656         if (adjtype) {
657                 if (adjtype->ty_SQList)
658                         RUNE_REMOVE(adjtype->ty_SQList, adjtype, ty_Node);
659                 adjtype->ty_SQList = &type->ty_QList;
660                 RUNE_INSERT_TAIL(adjtype->ty_SQList, adjtype, ty_Node);
661         }
662         return type;
663 }
664
665 /*
666  * Compound types inherit locking modes if not specifically
667  * overridden.
668  */
669 Type *
670 TypeFixupInheritedFlags(Type *type, int rqflags)
671 {
672         SemGroup *sg;
673         Declaration *d;
674
675         if (type->ty_Op != TY_COMPOUND)
676                 return type;
677
678         /*
679          * Assume no matching collapse yet
680          */
681         sg = type->ty_CompType.et_SemGroup;
682         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
683                 if (d->d_Op != DOP_GROUP_STORAGE)
684                         continue;
685                 if ((d->d_ScopeFlags & SCOPE_LOCKING_MASK) == 0) {
686                         if (rqflags & SF_UNTRACKED)
687                                 d->d_ScopeFlags |= SCOPE_UNTRACKED;
688                         if (rqflags & SF_UNLOCKED)
689                                 d->d_ScopeFlags |= SCOPE_UNLOCKED;
690                         if (rqflags & SF_SOFT)
691                                 d->d_ScopeFlags |= SCOPE_SOFT;
692                         if (rqflags & SF_HARD)
693                                 d->d_ScopeFlags |= SCOPE_HARD;
694                 }
695         }
696         return type;
697 }
698
699 Type *
700 TypeToQualType(Type *otype, Type *ntype, int sqFlags, Exp *exp)
701 {
702         SemGroup *sg;
703
704         /*
705          * Combine with existing qualifiers, Shortcut if no changes made.
706          */
707         if (ntype == NULL && 
708             sqFlags == otype->ty_SQFlags &&
709             (exp == NULL || exp == otype->ty_AssExp)
710         ) {
711                 return(otype);
712         }
713
714         /*
715          * See if we already have a matching qualified type (only if storage
716          * for the new type is not being provided).  Note: the provided storage
717          * has already been initType()d
718          */
719         if (ntype == NULL) {
720                 RUNE_FOREACH(ntype, otype->ty_SQList, ty_Node) {
721                         if (ntype->ty_Op == otype->ty_Op && 
722                             ntype->ty_SQFlags == sqFlags &&
723                             (exp == NULL || ntype->ty_AssExp == exp)
724                         ) {
725                                 if (SameType(ntype, otype, sqFlags))
726                                         return(ntype);
727                         }
728                 }
729         }
730
731         /*
732          * Build a new qualified type and set its qualifiers, then duplicate
733          * appropriate sections of the old type.
734          *
735          * Default to the same SQList as otype.
736          */
737         if (ntype == NULL) {
738                 ntype = AllocType(otype->ty_SQList, otype->ty_Op);
739         } else {
740                 if (ntype->ty_SQList)
741                         RUNE_REMOVE(ntype->ty_SQList, ntype, ty_Node);
742                 ntype->ty_SQList = otype->ty_SQList;
743                 RUNE_INSERT_TAIL(ntype->ty_SQList, ntype, ty_Node);
744         }
745
746         /*
747          * Set the op and the expression.  Unlike SQFlags, if exp is passed as
748          * NULL we inherit the old type's default.
749          *
750          * The DupExp() call here is special, see DupExp()'s handling of
751          * ex_Decl.
752          *
753          * Normally DupExp() is called during resolution prior to ex_Decl
754          * being set.  This is the one case where it may be called with
755          * ex_Decl already set.
756          *
757          * WARNING! We do not try to resolve the type here.  Various resolve
758          *          related flags in ty_Flags will be resolved later.  This
759          *          includes TF_ISUNSIGNED and other TF_* flags.
760          */
761         ntype->ty_Op = otype->ty_Op;
762         if (exp)
763                 ntype->ty_AssExp = exp;
764         else if (otype->ty_AssExp)
765                 ntype->ty_AssExp = SetDupExp(NULL, otype->ty_AssExp);
766         ntype->ty_SQFlags = sqFlags;
767         ntype->ty_Visibility = otype->ty_Visibility;
768
769         switch(otype->ty_Op) {
770         case TY_CLASS:
771                 /*
772                  * When updating the class, alternative forms are collapsed
773                  * into it's SemGroup->sg_ClassList and not into some
774                  * potentially long recursive chain based on ty_QList.
775                  */
776                 sg = otype->ty_ClassType.et_SemGroup;
777
778                 dassert(ntype->ty_SQList == &sg->sg_ClassList);
779                 if (ntype->ty_ClassType.et_SemGroup != sg) {
780                         ntype->ty_ClassType.et_SemGroup = sg;
781                 }
782                 ntype->ty_ClassType.et_Super = otype->ty_ClassType.et_Super;
783                 break;
784         case TY_IMPORT:
785                 ntype->ty_Visibility = otype->ty_Visibility;
786                 ntype->ty_ImportType.et_SemGroup = otype->ty_ImportType.et_SemGroup;
787                 break;
788         case TY_CPTRTO:
789                 ntype->ty_CPtrType.et_Type = otype->ty_CPtrType.et_Type;
790                 break;
791         case TY_PTRTO:
792                 ntype->ty_PtrType.et_Type = otype->ty_PtrType.et_Type;
793                 break;
794         case TY_REFTO:
795                 ntype->ty_RefType.et_Type = otype->ty_RefType.et_Type;
796                 break;
797         case TY_ARYOF:
798                 /*
799                  * note: multiple type structures may share the same array size
800                  * expression in simple qualified-type cases.  YYY XXX bad bad.
801                  */
802                 ntype->ty_AryType.et_Type = otype->ty_AryType.et_Type;
803                 ntype->ty_AryType.et_ArySize = otype->ty_AryType.et_ArySize;
804                 ntype->ty_AryType.et_SemGroup = otype->ty_AryType.et_SemGroup;
805                 ntype->ty_AryType.et_Count = otype->ty_AryType.et_Count;
806                 break;
807         case TY_COMPOUND:
808                 ntype->ty_CompType.et_SemGroup = otype->ty_CompType.et_SemGroup;
809                 break;
810         case TY_VAR:
811                 ntype->ty_VarType.et_Type = otype->ty_VarType.et_Type;
812                 ntype->ty_VarType.et_SemGroup = otype->ty_VarType.et_SemGroup;
813                 break;
814         case TY_ARGS:
815                 ntype->ty_ArgsType.et_SemGroup = otype->ty_ArgsType.et_SemGroup;
816                 break;
817         case TY_PROC:
818                 ntype->ty_ProcType.et_ArgsType = otype->ty_ProcType.et_ArgsType;
819                 ntype->ty_ProcType.et_RetType = otype->ty_ProcType.et_RetType;
820                 ntype->ty_ProcType.et_ArgCount = otype->ty_ProcType.et_ArgCount;
821                 dassert(ntype->ty_SQList ==
822                         &otype->ty_ProcType.et_RetType->ty_QList);
823                 break;
824         case TY_STORAGE:
825                 ntype->ty_StorType.et_Bytes = otype->ty_StorType.et_Bytes;
826                 break;
827         case TY_DYNAMIC:
828                 /*
829                  * It is not legal to qualify a dynamic type other then to
830                  * add or remove SF_LVALUE.
831                  */
832                 dpanic("Dynamic type cannot be qualified");
833                 break;
834         case TY_UNRESOLVED:
835                 ntype->ty_UnresType.et_DottedId =
836                         otype->ty_UnresType.et_DottedId;
837                 ntype->ty_UnresType.et_SemGroup =
838                         otype->ty_UnresType.et_SemGroup;
839                 ntype->ty_UnresType.et_ImportSemGroup =
840                         otype->ty_UnresType.et_ImportSemGroup;
841                 break;
842         default:
843                 dassert_type(otype, 0);
844         }
845         return(ntype);
846 }
847
848 /*
849  * Convert a return-type + argument-type into a procedure type.  If
850  * adjret is non-zero the return-type is converted to locked storage
851  * (which is generally what we want).
852  *
853  * Match the procedure type(s) (after adjustment?)
854  */
855 Type *
856 TypeToProcType(Type *rtype, Type *atype, int adjret)
857 {
858         Type *type;
859         runesize_t count = 0;
860         Declaration *d;
861         SemGroup *sg;
862
863         dassert_type(atype, atype->ty_Op == TY_ARGS);
864
865         if (adjret)
866                 rtype = TypeFixupInheritedFlags(rtype, rtype->ty_SQFlags);
867
868         sg = atype->ty_CompType.et_SemGroup;
869
870         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
871                 ++count;
872         }
873         RUNE_FOREACH(type, &rtype->ty_QList, ty_Node) {
874                 if (type->ty_Op == TY_PROC) {
875                         if (type->ty_ProcType.et_ArgsType == atype &&
876                             type->ty_ProcType.et_RetType == rtype &&
877                             type->ty_ProcType.et_ArgCount == count
878                         ) {
879                                 return(type);
880                         }
881                 }
882         }
883         type = AllocType(&rtype->ty_QList, TY_PROC);
884         type->ty_ProcType.et_ArgsType = AllocArgsType(sg);
885         type->ty_ProcType.et_RetType = rtype;
886         type->ty_ProcType.et_ArgCount = count;
887         return(type);
888 }
889
890 /*
891  * Convert type to pointer-to-type
892  */
893 Type *
894 TypeToPtrType(Type *otype)
895 {
896         Type *type;
897
898         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
899                 if (type->ty_Op == TY_PTRTO)
900                         return(type);
901         }
902         type = AllocType(&otype->ty_QList, TY_PTRTO);
903         type->ty_PtrType.et_Type = otype;
904         return(type);
905 }
906
907 /*
908  * Convert type to pointer-to-type
909  */
910 Type *
911 TypeToCPtrType(Type *otype)
912 {
913         Type *type;
914
915         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
916                 if (type->ty_Op == TY_CPTRTO)
917                         return(type);
918         }
919         type = AllocType(&otype->ty_QList, TY_CPTRTO);
920         type->ty_CPtrType.et_Type = otype;
921         return(type);
922 }
923
924 /*
925  * Convert type to ref-to-type
926  *
927  *      A reference type is similar to a pointer type except that the
928  *      resolver is not able to entirely know what it is pointing to.
929  *      The reference type is a superclass, but the actual type is 
930  *      stored in the run-time structure.
931  */
932 Type *
933 TypeToRefType(Type *otype)
934 {
935         Type *type;
936
937         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
938                 if (type->ty_Op == TY_REFTO)
939                         return(type);
940         }
941         type = AllocType(&otype->ty_QList, TY_REFTO);
942         type->ty_RefType.et_Type = otype;
943         return(type);
944 }
945
946 Type *
947 TypeToAryType(Type *otype, Exp *exp, SemGroup *sg)
948 {
949         Type *type;
950
951         /*
952          * XXX handle constant expression optimization for QList
953          * XXX handle qualifiers
954          */
955         type = AllocType(&otype->ty_QList, TY_ARYOF);
956         type->ty_AryType.et_ArySize = exp;
957         type->ty_AryType.et_Type = DelTypeQual(otype, SF_MASK_ARY_INHERIT);
958         type->ty_AryType.et_SemGroup = sg;
959         type->ty_SQFlags |= otype->ty_SQFlags & SF_MASK_ARY_INHERIT;
960         return(type);
961 }
962
963 #if 0
964
965 Type *
966 TypeToRunTimeAryType(Type *otype, int count)
967 {
968         Type *type;
969         Type *t2 = DelTypeQual(otype, SF_MASK_ARY_INHERIT);
970
971         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
972                 if (type->ty_Op == TY_ARYOF &&
973                         type->ty_AryType.et_Type == t2 &&
974                         type->ty_AryType.et_Count == count &&
975                         type->ty_SQFlags ==
976                          (otype->ty_SQFlags & SF_MASK_ARY_INHERIT)
977                 ) {
978                         return(type);
979                 }
980         }
981         type = AllocType(&otype->ty_QList, TY_ARYOF);
982         type->ty_AryType.et_Count = count;
983         type->ty_AryType.et_Type = t2;
984         type->ty_SQFlags |= otype->ty_SQFlags & SF_MASK_ARY_INHERIT;
985         return(type);
986 }
987
988 #endif
989
990 Type *
991 TypeToVarType(Type *otype, SemGroup *sg)
992 {
993         Type *type;
994
995         /*dassert(sg->sg_Flags & SGF_RESOLVED);*/
996         /*dassert(otype->ty_Flags & TF_RESOLVED);*/
997
998         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
999                 if (type->ty_Op == TY_VAR &&
1000                     type->ty_VarType.et_Type == otype &&
1001                     type->ty_VarType.et_SemGroup == sg
1002                 ) {
1003                         puts("SG2"); /* YYY */
1004                         return(type);
1005                 }
1006         }
1007         type = AllocType(&otype->ty_QList, TY_VAR);
1008         type->ty_VarType.et_Type = otype;
1009         type->ty_VarType.et_SemGroup = sg;
1010 #if 0
1011         /* XXX doesn't work for var-args */
1012         if (sg->sg_Flags & SGF_RESOLVED) {
1013                 type->ty_Flags |= TF_RESOLVED;
1014                 type->ty_Bytes = sg->sg_Bytes;
1015                 type->ty_AlignMask = sg->sg_AlignMask;
1016         }
1017 #endif
1018         return(type);
1019 }
1020
1021 /*
1022  * ChangeType() - given pointer, C pointer, or array of something,
1023  *                return 'op' of something instead.
1024  */
1025 Type *
1026 ChangeType(Type *type, int op)
1027 {
1028         switch(type->ty_Op) {
1029         case TY_PTRTO:
1030                 switch(op) {
1031                 case TY_CPTRTO:
1032                         type = TypeToCPtrType(type->ty_PtrType.et_Type);
1033                         break;
1034                 case TY_ARYOF:
1035                         type = TypeToAryType(type->ty_PtrType.et_Type,
1036                                              NULL, NULL);
1037                         break;
1038                 default:
1039                         dpanic("Illegal type convesion (A)");
1040                 }
1041                 break;
1042         case TY_CPTRTO:
1043                 switch(op) {
1044                 case TY_PTRTO:
1045                         type = TypeToPtrType(type->ty_CPtrType.et_Type);
1046                         break;
1047                 case TY_ARYOF:
1048                         type = TypeToAryType(type->ty_CPtrType.et_Type,
1049                                              NULL, NULL);
1050                         break;
1051                 default:
1052                         dpanic("Illegal type convesion (B)");
1053                 }
1054                 break;
1055         case TY_ARYOF:
1056                 switch(op) {
1057                 case TY_PTRTO:
1058                         type = TypeToPtrType(type->ty_AryType.et_Type);
1059                         break;
1060                 case TY_CPTRTO:
1061                         type = TypeToCPtrType(type->ty_AryType.et_Type);
1062                         break;
1063                 default:
1064                         dpanic("Illegal type convesion (C)");
1065                 }
1066                 break;
1067         default:
1068                 dpanic("Illegal type convesion (D)");
1069         }
1070         return(type);
1071 }
1072
1073 /*
1074  * BaseType() - return base type
1075  *
1076  *      Traverse the type to locate the base type.  Store the base type
1077  *      in *ptype and return the SemGroup, or return NULL if the base type
1078  *      does not have a SemGroup.
1079  */
1080 SemGroup *
1081 BaseType(Type **ptype)
1082 {
1083         Type *type = *ptype;
1084
1085         for (;;) {
1086                 switch(type->ty_Op) {
1087                 case TY_CPTRTO:
1088                         type = type->ty_CPtrType.et_Type;
1089                         continue;
1090                 case TY_PTRTO:
1091                         type = type->ty_PtrType.et_Type;
1092                         continue;
1093                 case TY_REFTO:
1094                         type = type->ty_RefType.et_Type;
1095                         continue;
1096                 case TY_ARYOF:
1097                         type = type->ty_AryType.et_Type;
1098                         continue;
1099                 }
1100                 break;
1101         }
1102
1103         *ptype = type;
1104
1105         switch(type->ty_Op) {
1106         case TY_CLASS:
1107                 return(type->ty_ClassType.et_SemGroup);
1108         case TY_COMPOUND:
1109                 return(type->ty_CompType.et_SemGroup);
1110         case TY_ARGS:
1111                 return(type->ty_ArgsType.et_SemGroup);
1112         case TY_PROC:
1113         case TY_VAR:
1114         case TY_DYNAMIC:
1115         case TY_STORAGE:
1116                 return(NULL);
1117         case TY_UNRESOLVED:
1118         default:
1119                 dassert_type(type, 0);
1120                 return(NULL);   /* avoid compiler complaints */
1121         }
1122 }
1123
1124 /*
1125  * DupType()     - create a duplicate of a type, possibly in a new SemGroup.
1126  *
1127  *      This code is used when duplicating procedures and other elements
1128  *      when merging a superclass into a subclass.
1129  *
1130  *      If sg is NULL, stype is simply returned.  The case is used when we
1131  *      try to duplciate an expression with DupExp()... in that case we
1132  *      want to dup the expression tree but use the same types.
1133  */
1134 Type *
1135 DupType(SemGroup *sg, Type *stype)
1136 {
1137         Type *type = NULL;
1138
1139         if (sg == NULL)
1140                 return(stype);
1141
1142         /*
1143          * XXX type may be resolved if it is part of a varargs dup
1144          */
1145 #if 0
1146         dassert_type(stype,
1147                      (stype->ty_Flags & (TF_RESOLVED|TF_RESOLVING)) == 0);
1148 #endif
1149
1150         switch(stype->ty_Op) {
1151         case TY_CLASS:
1152                 /*
1153                  * This only occurs because the resolver has resolved an
1154                  * unresolved type on the original SemGroup.  We duplicate
1155                  * that on the new SemGroup.
1156                  */
1157                 type = AllocClassType(&sg->sg_ClassList,
1158                                       stype->ty_ClassType.et_Super,
1159                                       stype->ty_ClassType.et_SemGroup,
1160                                       stype->ty_Visibility);
1161                 break;
1162         case TY_IMPORT:
1163         case TY_DYNAMIC:
1164                 type = stype;
1165                 break;
1166         case TY_CPTRTO:
1167                 type = TypeToCPtrType(DupType(sg, stype->ty_CPtrType.et_Type));
1168                 break;
1169         case TY_PTRTO:
1170                 type = TypeToPtrType(DupType(sg, stype->ty_PtrType.et_Type));
1171                 break;
1172         case TY_REFTO:
1173                 type = TypeToRefType(DupType(sg, stype->ty_RefType.et_Type));
1174                 break;
1175         case TY_ARYOF:
1176                 type = TypeToAryType(DupType(sg, stype->ty_AryType.et_Type),
1177                                 SetDupExp(sg, stype->ty_AryType.et_ArySize),
1178                                 stype->ty_AryType.et_SemGroup);
1179                 type->ty_AryType.et_Count = stype->ty_AryType.et_Count;
1180                 break;
1181         case TY_VAR:
1182                 type = TypeToVarType(DupType(sg, stype->ty_VarType.et_Type),
1183                                 DupSemGroup(sg, NULL,
1184                                             stype->ty_VarType.et_SemGroup, 1));
1185                 break;
1186         case TY_COMPOUND:
1187                 type = AllocCompoundType(
1188                                 DupSemGroup(sg, NULL,
1189                                             stype->ty_CompType.et_SemGroup, 1));
1190                 break;
1191         case TY_ARGS:
1192                 /*
1193                  * At the moment we always formally duplicate the arguments
1194                  * so we can modify them for methods below.
1195                  */
1196                 type = AllocArgsType(
1197                                 DupSemGroup(sg, NULL,
1198                                             stype->ty_CompType.et_SemGroup, 1));
1199                 break;
1200         case TY_PROC:
1201                 type = DupType(sg, stype->ty_ProcType.et_RetType);
1202                 type = TypeToProcType(type,
1203                                   DupType(sg, stype->ty_ProcType.et_ArgsType),
1204                                       1);
1205
1206                 /*
1207                  * If this is a method procedure, we have to change the
1208                  * first argument to point at our new subclass.  It was
1209                  * previously pointing at our superclass.   XXX the
1210                  * programmer can override the argument.  If it isn't a
1211                  * reference we have to assert.
1212                  */
1213                 if (sg->sg_Stmt->st_Op != ST_Class) {
1214                         /*
1215                          * XXX probably an inlined procedure, the type is
1216                          *     already correct.  Need an assertrion here.
1217                          */
1218                 } else if (stype->ty_SQFlags & SF_METHOD) {
1219                         SemGroup *asg = type->ty_ProcType.et_ArgsType->ty_ArgsType.et_SemGroup;
1220                         Declaration *d = RUNE_FIRST(&asg->sg_DeclList);
1221                         Type *thisType = d->d_StorDecl.ed_Type;
1222
1223                         dassert_decl(d, d->d_Id == String_This &&
1224                                         d->d_Op == DOP_ARGS_STORAGE);
1225                         dassert_decl(d, sg->sg_Stmt->st_Op == ST_Class);
1226                         if (thisType->ty_Op == TY_CLASS) {
1227                                 /* XXX sg_ClassList? right sg? */
1228                                 /* XXX correct visibility? */
1229                                 if (d->d_Search == NULL) {
1230                                         d->d_Search = d->d_StorDecl.ed_Type->
1231                                                       ty_ClassType.et_SemGroup;
1232                                 }
1233                                 d->d_StorDecl.ed_Type =
1234                                         AllocClassType(&sg->sg_ClassList,
1235                                                        sg->sg_Stmt->st_ClassStmt.es_Super,
1236                                                        sg->sg_Stmt->st_MyGroup,
1237                                                        SCOPE_ALL_VISIBLE);
1238                         } else {
1239                                 dassert_decl(d, thisType->ty_Op == TY_REFTO);
1240                         }
1241                 } else if (stype->ty_SQFlags & SF_GMETHOD) {
1242                         SemGroup *asg;
1243                         Declaration *d;
1244
1245                         asg = type->ty_ProcType.et_ArgsType->
1246                                 ty_ArgsType.et_SemGroup;
1247                         d = RUNE_FIRST(&asg->sg_DeclList);
1248
1249                         dassert_decl(d, d->d_Id == String_This &&
1250                                      d->d_Op == DOP_TYPEDEF);
1251                         dassert_decl(d, sg->sg_Stmt->st_Op == ST_Class);
1252                         dassert_decl(d, d->d_TypedefDecl.ed_Type->ty_Op ==
1253                                         TY_CLASS);
1254                         /* XXX sg_ClassList? right sg? */
1255                         /* XXX correct visibility? */
1256                         if (d->d_Search == NULL) {
1257                                 d->d_Search = d->d_TypedefDecl.ed_Type->
1258                                                ty_ClassType.et_SemGroup;
1259                         }
1260                         d->d_TypedefDecl.ed_Type =
1261                                 AllocClassType(&sg->sg_ClassList,
1262                                                sg->sg_Stmt->st_ClassStmt.es_Super,
1263                                                sg->sg_Stmt->st_MyGroup,
1264                                                SCOPE_ALL_VISIBLE);
1265                 }
1266                 break;
1267         case TY_STORAGE:
1268                 type = stype;
1269                 break;
1270         case TY_UNRESOLVED:
1271                 /*
1272                  * e.g. so elements in a superclass will see refined elements
1273                  * in the subclass.  Note that the original import semgroup
1274                  * is left intact so the semantic search mechanism uses it
1275                  * when the base sg (typically a subclass) fails.
1276                  */
1277                 type = AllocUnresolvedType(
1278                                 stype->ty_UnresType.et_ImportSemGroup,
1279                                 sg,
1280                                 stype->ty_UnresType.et_DottedId,
1281                                 0);
1282                 break;
1283         default:
1284                 dassert_type(stype, 0);
1285         }
1286
1287         if (type != stype) {
1288                 type->ty_Flags = stype->ty_Flags &
1289                                  ~(TF_ISINTERNAL | TF_RESOLVING | TF_RESOLVED |
1290                                    TF_ALIGNRESOLVED | TF_TMPRESOLVED);
1291                 type->ty_Bytes = stype->ty_Bytes;
1292                 type->ty_AlignMask = stype->ty_AlignMask;
1293                 type->ty_Visibility = stype->ty_Visibility;
1294                 type->ty_DynamicVector = stype->ty_DynamicVector;
1295         }
1296         if (stype->ty_AssExp || stype->ty_SQFlags != type->ty_SQFlags) {
1297                 type = TypeToQualType(type, NULL,
1298                                       stype->ty_SQFlags,
1299                                       SetDupExp(sg, stype->ty_AssExp));
1300         }
1301
1302         return(type);
1303 }
1304
1305 typereglist_t TypeRegList = RUNE_HEAD_INITIALIZER(TypeRegList);
1306
1307 void
1308 InternalRegisterType(const char *str, const char *linkname, Type *type)
1309 {
1310         static int Special = SPECIALF_REGISTERED|SPECIALF_INTERNAL|1;
1311         TypeRegNode *tr;
1312
1313         dassert(Special & SPECIALF_MASK);
1314         tr = zalloc(sizeof(TypeRegNode));
1315         tr->tr_Id = StrTableAlloc(str, strlen(str), Special++);
1316         tr->tr_Type = type;
1317         tr->tr_LinkName = linkname;
1318         RUNE_INSERT_TAIL(&TypeRegList, tr, tr_Node);
1319 }
1320
1321 Type *
1322 InternalRegisteredTypeLookup(string_t id)
1323 {
1324         TypeRegNode *tr;
1325
1326         RUNE_FOREACH(tr, &TypeRegList, tr_Node) {
1327                 if (tr->tr_Id == id)
1328                         return(tr->tr_Type);
1329         }
1330         return(NULL);
1331 }