rune - Features and work
[rune.git] / librune / resolve.c
1 /*
2  * RESOLVE.C    - Resolve parser tree
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  *
7  * This module is responsible for resolving unresolved types and
8  * classes, generating offsets for DeclBlock's and declarations, and
9  * resolving type-rules for expressions in the expression tree.
10  *
11  * We can reach the entire tree by resolving the top-level import
12  * statement's DeclBlock.
13  */
14
15 #include "defs.h"
16 #include <dlfcn.h>
17
18 static void ResolveClasses(Stmt *st);
19 static void ResolveTypes(SemGroup *isg, Stmt *st);
20 static void ResolveStorage(Stmt *st);
21 static void errorDottedId(string_t *ary, const char *ctl, ...);
22
23 static Type *resolveReturnType(SemGroup *sg);
24 static Type *resolveArgsType(SemGroup *sg);
25 static void resolveDecl(Declaration *d);
26 static Exp *resolveExp(SemGroup *isg, SemGroup *sg,
27                         Exp *exp, Type *itype, int autocast);
28 static Exp *resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp);
29 static Exp *resolveCompoundExp(SemGroup *isg, SemGroup *sg,
30                         Exp *exp, Type *itype);
31 static Exp *resolveExpCast(SemGroup *isg, SemGroup *sg,
32                         Exp *exp, Type *ltype);
33 static Exp *resolveExpOper(SemGroup *isg, SemGroup *sg,
34                         Exp *exp, Type *itype);
35 static int resolveSemGroup1(SemGroup *sg);
36 static void resolveSemGroup2(SemGroup *sg);
37 static Type *resolveSuperClass(Type *super);
38 static void resolveStorageDeclExp(Declaration *d,
39                         runesize_t *offset, runesize_t *goffset);
40 static runesize_t resolveStorageExpOnly(Exp *exp, runesize_t *offset);
41 static void resolveStorageExpSub(Exp *exp, runesize_t *offset);
42 static void resolveStorageExp(Exp *exp, runesize_t *offset);
43
44 static Declaration *findOper(Type *btype, string_t id,
45                         Type *ltype, Type *rtype);
46 static Declaration *findExpOper(Exp *exp);
47 static Declaration *findCast(Type *btype, Type *ltype, Type *rtype);
48 static void loadExpCopy(Exp *copy, Exp *exp);
49 static void saveExpCopy(Exp *copy, Exp *exp);
50 static Exp *dupExpCopy(Exp *copy, Exp *exp);
51 static void resolveStorageType(Type *type);
52 static void resolveStorageSemGroup(SemGroup *sg,
53                         runesize_t noffset, runesize_t ngoffset);
54
55 #define exLhs           copy.ex_Lhs
56 #define exRhs           copy.ex_Rhs
57 #define exFlags         copy.ex_Flags
58 #define exType          copy.ex_Type
59 #define exToken         copy.ex_Token
60 #define exDecl          copy.ex_Decl
61 #define exVisibility    copy.ex_Visibility
62 #define exId            copy.ex_Id
63 #define exArgId         copy.ex_ArgId
64
65 #define ADD_LVALUE(type)        resolveType(AddTypeQual((type), SF_LVALUE))
66 #define DEL_LVALUE(type)        resolveType(DelTypeQual((type), SF_LVALUE))
67
68 void
69 ResolveProject(Parse *p, Stmt *st)
70 {
71         dassert_stmt(st, st->st_Op == ST_Import);
72         ResolveClasses(st);
73         ResolveTypes(st->st_MyGroup, st);
74         ResolveStorage(st);
75         p->p_Format = PFMT_RESOLVED;
76 }
77
78 /*
79  * ResolveClasses() -   Resolve superclasses and do class merge 
80  *
81  *      This code implements the most complex feature of the language:
82  *      subclassing and refinement.  
83  *
84  *      The hardest thing we have to do is 'dup' declarations and code in
85  *      order to implement subclassing and refinement.  For example, a
86  *      procedure defined in Integer must be dup'd for each subclass of
87  *      Integer.  We have to do this because storage requirements will
88  *      change due to both subclassing and refinement.  Even auto variables
89  *      may wind up with different types between superclass and subclass.
90  *
91  *      We must scan ST_Import and ST_Class statements.
92  */
93 static void
94 ResolveClasses(Stmt *st)
95 {
96         SemGroup *sg = st->st_MyGroup;
97
98         /*
99          * Resolver interlock.  Assert that we aren't looping.  A loop can
100          * occur if class A embeds class B and class B embeds class A
101          * (verses a pointer to A).
102          */
103         dassert_stmt(st, (st->st_Flags & STF_RESOLVING) == 0);
104         if (st->st_Flags & STF_RESOLVED)
105                 return;
106         st->st_Flags |= STF_RESOLVING;
107
108         /*
109          * If this is a subclass, integrate the superclass into it
110          */
111         if (st->st_Op == ST_Class && st->st_ClassStmt.es_Super) {
112                 Type *super = st->st_ClassStmt.es_Super;
113                 Stmt *sst;
114                 Declaration *d;
115                 Declaration *rd;
116                 SemGroup *tsg;
117
118                 /*
119                  * Locate the superclass.  'super' does not appear in any
120                  * other list.. this is a unique Type structure.
121                  */
122                 dassert_stmt(st, super->ty_Op == TY_UNRESOLVED);
123                 do {
124                         super = resolveSuperClass(super);
125                         if (super == NULL) {
126                                 fprintf(stderr,
127                                         "Unable to resolve superclass of %s\n",
128                                         st->st_ClassStmt.es_Decl->d_Id);
129                                 dassert_stmt(st, 0);
130                         }
131                 } while (super->ty_Op == TY_UNRESOLVED);
132
133                 dassert_stmt(st, super->ty_Op == TY_CLASS);
134
135                 /*
136                  * Cleanup (XXX free qualified segments??)
137                  */
138                 st->st_ClassStmt.es_Super = super;
139                 st->st_ClassStmt.es_Decl->d_ClassDecl.ed_Super = super;
140
141                 /*
142                  * Inherit internal unsigned integer and floating point flags.
143                  */
144                 sg->sg_Flags |= super->ty_ClassType.et_SemGroup->sg_Flags &
145                                 (SGF_ISUNSIGNED | SGF_ISFLOATING);
146
147                 /*
148                  * Locate the class statement associated with the superclass
149                  * and resolve it.
150                  */
151                 sst = super->ty_ClassType.et_SemGroup->sg_Stmt;
152                 dassert_stmt(st, sst != NULL);
153                 dassert_stmt(st, sst->st_Op == ST_Class);
154
155                 ResolveClasses(sst);
156
157                 /*
158                  * Assign the sg_Level for the subclass.  This is used
159                  * for semantic searches when a subclass is passed to a
160                  * procedure expecting the superclass.
161                  */
162                 sg->sg_Level = sst->st_MyGroup->sg_Level + 1;
163
164                 /*
165                  * First move all the declarations from sg to tsg so we
166                  * can merge the superclass properly (keep all the d_Index's
167                  * correct).  Note that tsg is not 100% integrated so we can
168                  * only use it for search purposes.  We absolutely CANNOT
169                  * DupDeclaration() into tsg!
170                  */
171                 tsg = AllocSemGroup(sg->sg_Parse, NULL, sg->sg_Stmt);
172                 while ((d = getHead(&sg->sg_DeclList)) != NULL) {
173                         RenameDecl(d, tsg);
174                 }
175                 sg->sg_DeclCount = 0;   /* reset */
176
177                 /*
178                  * Merge the superclass into this class, in sequence.
179                  * Iterate through declarations in the superclass and pull
180                  * them into the subclass.  Figure out compatibility between
181                  * super and subclasses.
182                  */
183                 for (
184                         d = getHead(&sst->st_MyGroup->sg_DeclList);
185                         d;
186                         d = getSucc(&sst->st_MyGroup->sg_DeclList, &d->d_Node)
187                 ) {
188                         Declaration *nd;
189                         int eno = 0;
190
191                         dassert(d->d_Level != NULL &&
192                                 d->d_Level->sg_Level < sg->sg_Level);
193
194                         /*
195                          * See if the superclass decl conflicts with a
196                          * subclass decl.  If there is no conflict pull it
197                          * into the subclass and adjust the visibility.
198                          * Note that the superclass may have duplicate ids,
199                          * but they will be at different levels if so.
200                          *
201                          * The super linkage is required when findDecl()
202                          * checks visibility of a declaration hidden relative
203                          * to our subclass, but not necessarily hidden
204                          * relative to the superclass.
205                          *
206                          * XXX overloading
207                          */
208                         rd = FindDeclId(tsg, d->d_Id, &eno);
209                         if (rd == NULL) {
210                                 nd = DupDeclaration(sg, d);
211                                 dassert(d->d_Index == nd->d_Index);
212                                 nd->d_ScopeFlags &= ~SCOPE_ALL_VISIBLE |
213                                                     super->ty_Visibility;
214                                 nd->d_ScopeFlags &= ~SCOPE_REFINE;
215                                 continue;
216                         }
217
218                         /*
219                          * If there is a conflict and we are not refining
220                          * the superclass entity, then pull it in and make
221                          * it invisible to sg_Level searches.  This could
222                          * bring in multiple levels of the same id.
223                          *
224                          * Note that this may result in multiple ids, but
225                          * they will be at different levels.  In this case
226                          * rd will be at the current level and nd will be
227                          * at some prior level.
228                          */
229                         if ((rd->d_ScopeFlags & SCOPE_REFINE) == 0) {
230                                 nd = DupDeclaration(sg, d);
231                                 dassert(d->d_Index == nd->d_Index);
232                                 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
233                                                       SCOPE_REFINE);
234 #if 0
235                                 printf(" conflict, not refined, overload\n");
236 #endif
237                                 continue;
238                         }
239
240                         /*
241                          * Ok, we need to refine.  But the superclass may
242                          * contain multiple levels of the same id.  We only
243                          * refine the one that is visible to us.  None of
244                          * these other declarations will be at the same level.
245                          */
246                         if ((d->d_ScopeFlags & SCOPE_ALL_VISIBLE) == 0) {
247                                 nd = DupDeclaration(sg, d);
248                                 dassert(d->d_Index == nd->d_Index);
249                                 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
250                                                       SCOPE_REFINE);
251 #if 0
252                                 printf(" conflict, refined (skip this one)\n");
253 #endif
254                                 continue;
255                         }
256
257                         /*
258                          * Whew!  Finally, we found the superclass decl
259                          * that we wish to refine.  We had better not have
260                          * already refined it or there's something wrong
261                          * with the algorithm.
262                          *
263                          * Since we inherit the superclass method's level
264                          * our method will run in the superclass instead
265                          * of the original, but d_Super still must be set
266                          * for findDecl() to track down visibility relative
267                          * to the superclass methods.
268                          */
269                         RenameDecl(rd, sg);
270                         dassert_decl(rd, rd->d_Super == NULL);
271                         dassert(d->d_Index == rd->d_Index);
272                         rd->d_Level = d->d_Level;
273                         rd->d_Super = d;
274
275                         /*
276                          * This is for the superclass method access special
277                          * case below.
278                          */
279                         if (d->d_Op == DOP_PROC) {
280                                 d->d_Flags |= DF_SUPERCOPY;
281                         }
282                 }
283
284                 /*
285                  * Deal with any remaining elements in tsg.  These are
286                  * 'extensions' to the superclass.  There may also be
287                  * invisible DOP_PROC's to handle the special superclass
288                  * method call case descibed above.
289                  */
290                 while ((rd = getHead(&tsg->sg_DeclList)) != NULL) {
291                         if (rd->d_ScopeFlags & SCOPE_REFINE) {
292                                 if (rd->d_Super == NULL) {
293                                         fprintf(stderr,
294                                                 "Unable to refine %s, it "
295                                                 "does not exist in "
296                                                 "superclass\n",
297                                                 rd->d_Id);
298                                         dassert_decl(rd, 0);
299                                 }
300                         }
301                         RenameDecl(rd, sg);
302                 }
303
304                 FreeSemGroup(tsg);
305
306                 /*
307                  * We have to special case super.method() for a refined method.
308                  * Normally this makes the original method inaccessible (for
309                  * storage), but we want it to work for a procedure so we make
310                  * a copy in tsg.  (we can't dup it directly into sg because it
311                  * will screw up the d_Index).
312                  *
313                  * We must not only clear the scope visibility and the
314                  * temporary refine flag, we also have to clear
315                  * constructor/destructor scope in the copy so only the
316                  * refined constructor/destructor is called, not both the
317                  * refined and the superclass constructor/destructor.
318                  */
319                 for (
320                         d = getHead(&sst->st_MyGroup->sg_DeclList);
321                         d;
322                         d = getSucc(&sst->st_MyGroup->sg_DeclList, &d->d_Node)
323                 ) {
324                         Declaration *nd;
325
326                         if (d->d_Flags & DF_SUPERCOPY) {
327                                 d->d_Flags &= ~DF_SUPERCOPY;
328                                 nd = DupDeclaration(sg, d);
329                                 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
330                                                       SCOPE_REFINE |
331                                                       SCOPE_CONSTRUCTOR |
332                                                       SCOPE_DESTRUCTOR);
333                         }
334                 }
335         } else if (st->st_Op == ST_Class) {
336                 sg->sg_Level = 0;
337         }
338
339         st->st_Flags &= ~STF_RESOLVING;
340         st->st_Flags |= STF_RESOLVED;
341
342         /*
343          * If this is an ST_Import we must recurse through it.  The only
344          * statements under an Import should be Modules.  Well, really just
345          * one module.  And under that module we only care about ST_Import
346          * and ST_Class statements.
347          *
348          * If this is a shared import the statement list will be empty (later
349          * it may be used for import refinement, I dunno).  This is what we
350          * want since we should only resolve a shared import once.
351          */
352         if (st->st_Op == ST_Import) {
353                 Stmt *scan;
354
355                 for (
356                         scan = getHead(&st->st_List);
357                         scan;
358                         scan = getSucc(&st->st_List, &scan->st_Node)
359                 ) {
360                         Stmt *scan2;
361
362                         dassert_stmt(scan, scan->st_Op == ST_Module);
363                         for (
364                                 scan2 = getHead(&scan->st_List);
365                                 scan2;
366                                 scan2 = getSucc(&scan->st_List, &scan2->st_Node)
367                         ) {
368                                 if (scan2->st_Op == ST_Import ||
369                                     scan2->st_Op == ST_Class) {
370                                         ResolveClasses(scan2);
371                                 }
372                         }
373                 }
374                 if (st->st_ImportStmt.es_DLL) {
375                         void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
376                                                    "resolveClasses");
377                         if (func)
378                                 func();
379                 }
380         }
381 }
382
383 /*
384  * ResolveTypes() - Resolve all types, declarations, and semantic refs
385  *
386  *      Resolves all types, declarations, and identifiers.  Additionally
387  *      this function resolves intermediate types for expressions.  Storage
388  *      sizes are resolved but offsets are not assigned to declarations.
389  */
390 void
391 ResolveTypes(SemGroup *isg, Stmt *st)
392 {
393         /*
394          * Deal with unresolved types here
395          */
396         if (st->st_Flags & STF_SEMANTIC) {
397                 SemGroup *sg = st->st_MyGroup;
398                 Type *type;
399
400                 for (
401                         type = getHead(&sg->sg_ClassList);
402                         type;
403                         type = getSucc(&sg->sg_ClassList, &type->ty_Node)
404                 ) {
405                         if (type->ty_Op == TY_UNRESOLVED) {
406                                 if (resolveSuperClass(type) == NULL) {
407                                         errorDottedId(
408                                                 type->ty_UnresType.et_DottedId,
409                                                 "Unable to resolve class");
410                                         dassert_stmt(st, 0);
411                                 }
412                         }
413                 }
414         }
415
416         /*
417          * Resolve statements.  Don't worry about declarations, those are
418          * handled after this switch.
419          */
420         switch(st->st_Op) {
421         case ST_Import:
422         case ST_Module:
423                 /*
424                  * Recursively resolve contents
425                  */
426                 {
427                         Stmt *scan;
428                         for (
429                                 scan = getHead(&st->st_List);
430                                 scan;
431                                 scan = getSucc(&st->st_List, &scan->st_Node)
432                         ) {
433                                 /*
434                                  * XXX pass isg for import, st_MyGroup for
435                                  * module??
436                                  */
437                                 ResolveTypes(st->st_MyGroup, scan);
438                         }
439                         if (st->st_Op == ST_Import &&
440                             st->st_ImportStmt.es_DLL) {
441                                 void (*func)(void) =
442                                         dlsym(st->st_ImportStmt.es_DLL,
443                                               "resolveTypes");
444                                 if (func)
445                                         func();
446                         }
447                 }
448                 break;
449         case ST_Class:
450                 resolveDecl(st->st_ClassStmt.es_Decl);
451                 break;
452         case ST_Typedef:
453                 resolveDecl(st->st_TypedefStmt.es_Decl);
454                 break;
455         case ST_Decl:
456                 {
457                         Declaration *d = st->st_DeclStmt.es_Decl;
458                         int i;
459
460                         for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
461                                 resolveDecl(d);
462                                 d = getSucc(&d->d_MyGroup->sg_DeclList,
463                                             &d->d_Node);
464                         }
465                 }
466                 break;
467         case ST_Block:
468                 {
469                         Stmt *scan;
470                         for (
471                                 scan = getHead(&st->st_List);
472                                 scan;
473                                 scan = getSucc(&st->st_List, &scan->st_Node)
474                         ) {
475                                 ResolveTypes(isg, scan);
476                         }
477                 }
478                 break;
479         case ST_Nop:
480                 break;
481         case ST_Loop:
482                 if (st->st_LoopStmt.es_Init)
483                         ResolveTypes(isg, st->st_LoopStmt.es_Init);
484                 if (st->st_LoopStmt.es_BCond) {
485                         /*
486                          * NOTE: BoolType global implies an rvalue.
487                          */
488                         st->st_LoopStmt.es_BCond =
489                                 resolveExp(isg, st->st_MyGroup,
490                                            st->st_LoopStmt.es_BCond,
491                                            &BoolType, 1);
492                 }
493                 if (st->st_LoopStmt.es_ACond) {
494                         /*
495                          * NOTE: BoolType global implies an rvalue.
496                          */
497                         st->st_LoopStmt.es_ACond =
498                                 resolveExp(isg, st->st_MyGroup,
499                                            st->st_LoopStmt.es_ACond,
500                                            &BoolType, 1);
501                 }
502                 if (st->st_LoopStmt.es_AExp) {
503                         /*
504                          * NOTE: VoidType global implies an rvalue.
505                          */
506                         st->st_LoopStmt.es_AExp =
507                                 resolveExp(isg, st->st_MyGroup,
508                                            st->st_LoopStmt.es_AExp,
509                                            &VoidType, 1);
510                 }
511                 if (st->st_LoopStmt.es_Body) {
512                         ResolveTypes(isg, st->st_LoopStmt.es_Body);
513                 }
514                 break;
515         case ST_BreakCont:
516                 break;
517         case ST_Bad:
518                 break;
519         case ST_IfElse:
520                 /*
521                  * NOTE: BoolType global implies an rvalue.
522                  */
523                 st->st_IfStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
524                                                   st->st_IfStmt.es_Exp,
525                                                   &BoolType, 1);
526                 ResolveTypes(isg, st->st_IfStmt.es_TrueStmt);
527                 if (st->st_IfStmt.es_FalseStmt)
528                         ResolveTypes(isg, st->st_IfStmt.es_FalseStmt);
529                 break;
530         case ST_Return:
531                 /*
532                  * NOTE: lvalue/rvalue depends on return type.
533                  */
534                 st->st_RetStmt.es_ProcRetType =
535                                 resolveReturnType(st->st_MyGroup);
536                 if (st->st_RetStmt.es_Exp) {
537                         st->st_RetStmt.es_Exp =
538                                 resolveExp(isg, st->st_MyGroup,
539                                            st->st_RetStmt.es_Exp,
540                                            st->st_RetStmt.es_ProcRetType, 1);
541                 }
542                 break;
543         case ST_Result:
544                 /*
545                  * NOTE: lvalue/rvalue depends on return type.
546                  */
547                 st->st_ResStmt.es_ProcRetType =
548                                 resolveReturnType(st->st_MyGroup);
549                 if (st->st_ResStmt.es_Exp) {
550                         st->st_ResStmt.es_Exp =
551                                 resolveExp(isg, st->st_MyGroup,
552                                            st->st_ResStmt.es_Exp,
553                                            st->st_ResStmt.es_ProcRetType, 1);
554                 }
555                 break;
556         case ST_Switch:
557                 /*
558                  * NOTE: Switch type must be an rvalue.
559                  *
560                  * NOTE: It is possible to switch on a type.  See ST_Case
561                  *       below for more detail.
562                  */
563                 st->st_SwStmt.es_Exp->ex_Flags |= EXF_REQ_TYPE;
564                 st->st_SwStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
565                                                   st->st_SwStmt.es_Exp,
566                                                   NULL, 0);
567
568                 /*
569                  * Switch-on-expression() expects an rvalue.
570                  */
571                 if ((st->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE) == 0) {
572                         st->st_SwStmt.es_Exp->ex_Type =
573                                 DEL_LVALUE(st->st_SwStmt.es_Exp->ex_Type);
574                 }
575                 {
576                         Stmt *scan;
577                         for (
578                                 scan = getHead(&st->st_List);
579                                 scan;
580                                 scan = getSucc(&st->st_List, &scan->st_Node)
581                         ) {
582                                 ResolveTypes(isg, scan);
583                         }
584                 }
585                 break;
586         case ST_Case:
587                 /*
588                  * Handle a case/default.  Note that when switching on a type,
589                  * each case expression must return a type.
590                  *
591                  * NOTE: Case type must be an rvalue.  We use the switch type
592                  *       to cast, so it will be.
593                  */
594                 {
595                         Stmt *scan;
596                         Exp *exp;
597                         Type *type;
598
599                         /*
600                          * Set type to cast cases to if we are switching on
601                          * an expression, otherwise we are switching on a
602                          * type and should not try to coerce the cases (it
603                          * doesn't make sense to).
604                          */
605                         dassert_stmt(st, st->st_Parent->st_Op == ST_Switch);
606                         if (st->st_Parent->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE)
607                                 type = NULL;
608                         else
609                                 type = st->st_Parent->st_SwStmt.es_Exp->ex_Type;
610
611                         /*
612                          * case: (if es_Exp is NULL, this is a default: )
613                          */
614                         if ((exp = st->st_CaseStmt.es_Exp) != NULL) {
615                                 if (type == NULL)
616                                         exp->ex_Flags |= EXF_REQ_TYPE;
617                                 exp = resolveExp(isg, st->st_MyGroup,
618                                                  exp, type, 1);
619                                 if (type == NULL)
620                                         dassert(exp->ex_Flags & EXF_RET_TYPE);
621                                 st->st_CaseStmt.es_Exp = exp;
622                         }
623
624                         /*
625                          * Elements of the case/default
626                          */
627                         for (
628                                 scan = getHead(&st->st_List);
629                                 scan;
630                                 scan = getSucc(&st->st_List, &scan->st_Node)
631                         ) {
632                                 ResolveTypes(isg, scan);
633                         }
634                 }
635                 break;
636         case ST_Exp:
637                 /*
638                  * NOTE: VoidType global implies an rvalue.
639                  *
640                  * NOTE: If resolveExp() doesn't cast to void for
641                  *       us, we will do it here.
642                  */
643                 {
644                         Exp *exp;
645
646                         exp = resolveExp(isg, st->st_MyGroup,
647                                          st->st_ExpStmt.es_Exp,
648                                          &VoidType, 1);
649                         if (exp->ex_Type != &VoidType) {
650                                 exp = resolveExpCast(isg, st->st_MyGroup,
651                                                      exp, &VoidType);
652                         }
653                         st->st_ExpStmt.es_Exp = exp;
654                 }
655                 break;
656         case ST_Proc:
657                 {
658                         Stmt *scan;
659                         for (
660                                 scan = getHead(&st->st_List);
661                                 scan;
662                                 scan = getSucc(&st->st_List, &scan->st_Node)
663                         ) {
664                                 ResolveTypes(isg, scan);
665                         }
666                 }
667                 break;
668         case ST_ThreadSched:
669                 break;
670         default:
671                 dassert_stmt(st, 0);
672         }
673 }
674
675 /*
676  * Locate the ST_Proc statement and resolve & return its return type
677  */
678 static
679 Type *
680 resolveReturnType(SemGroup *sg)
681 {
682         Declaration *d;
683         Type *type;
684         Stmt *st;
685
686         /*
687          * Locate the ST_Proc statement
688          */
689         while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
690                 sg = sg->sg_Parent;
691         dassert(sg != NULL);
692         st = sg->sg_Stmt;
693         d = st->st_ProcStmt.es_Decl;    /* decl is already resolved */
694         dassert_decl(d, d->d_Op == DOP_PROC);
695         dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
696         type = d->d_ProcDecl.ed_Type;
697         dassert_decl(d, type->ty_Op == TY_PROC);
698         return(type->ty_ProcType.et_RetType);
699 }
700
701 Type *
702 resolveArgsType(SemGroup *sg)
703 {
704         Declaration *d;
705         Type *type;
706         Stmt *st;
707
708         /*
709          * Locate the ST_Proc statement
710          */
711         while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
712                 sg = sg->sg_Parent;
713         dassert(sg != NULL);
714         st = sg->sg_Stmt;
715         d = st->st_ProcStmt.es_Decl;    /* decl is already resolved */
716         dassert_decl(d, d->d_Op == DOP_PROC);
717         dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
718         type = d->d_ProcDecl.ed_Type;
719         dassert_decl(d, type->ty_Op == TY_PROC);
720         return(type->ty_ProcType.et_ArgsType);
721 }
722
723 /*
724  * resolveDecl() - resolve a declaration
725  *
726  *      Note: we do not resolve d_Offset here.
727  *
728  *      If the declaration represents a procedure argument, special
729  *      processing of LVALUE scope is required to pass the declaration
730  *      by reference instead of by value.  Note that the size of the
731  *      underlying type DOES NOT CHANGE... it may be much larger.
732  */
733 void
734 resolveDecl(Declaration *d)
735 {
736         Type *type;
737         Stmt *st;
738         SemGroup *sg = NULL;
739
740         if (d->d_Flags & DF_RESOLVED)
741                 return;
742         dassert_decl(d, (d->d_Flags & DF_RESOLVING) == 0);
743         d->d_Flags |= DF_RESOLVING;
744
745         switch(d->d_Op) {
746         case DOP_CLASS:
747                 if (d->d_ClassDecl.ed_Super) {
748                         d->d_ClassDecl.ed_Super =
749                                 resolveType(d->d_ClassDecl.ed_Super);
750                 }
751                 sg = d->d_ClassDecl.ed_SemGroup;
752                 if (resolveSemGroup1(sg))
753                         resolveSemGroup2(sg);
754                 d->d_Bytes = d->d_ClassDecl.ed_SemGroup->sg_Bytes;
755                 d->d_AlignMask = d->d_ClassDecl.ed_SemGroup->sg_AlignMask;
756                 break;
757         case DOP_ALIAS:
758                 /*
759                  * Alias access is a barrier and always returns an rvalue.
760                  */
761                 type = d->d_AliasDecl.ed_Type =
762                                 resolveType(d->d_AliasDecl.ed_Type);
763                 if (d->d_AliasDecl.ed_AssExp) {
764                         d->d_AliasDecl.ed_AssExp =
765                                 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
766                                            d->d_AliasDecl.ed_AssExp,
767                                            DEL_LVALUE(type), 1);
768                 }
769                 /* handled in DOT and STRIND resolver */
770                 SetDupExp(NULL, d->d_AliasDecl.ed_AssExp);
771                 break;
772         case DOP_TYPEDEF:
773                 d->d_Flags |= DF_RESOLVED;
774                 type = resolveType(d->d_TypedefDecl.ed_Type); 
775                 d->d_Flags &= ~DF_RESOLVED;
776                 d->d_TypedefDecl.ed_Type = type;
777                 break;
778         case DOP_IMPORT:
779                 /*
780                  * This only occurs when resolving an import's semantic group.
781                  * Since we are scanning statements in that context we do not
782                  * have to recurse here, ResolveTypes() will do it for us.
783                  */
784                 break;
785         case DOP_PROC:
786                 /*
787                  * XXX global procedure, later on, make the argument a
788                  * type instead of storage?
789                  */
790                 d->d_ProcDecl.ed_Type = resolveType(d->d_ProcDecl.ed_Type);
791
792                 /*
793                  * Deal with constructor/destructor chaining.  The chaining
794                  * winds up being reversed and will be corrected by the caller.
795                  */
796                 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
797                         if (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
798                                                SCOPE_DESTRUCTOR)) {
799                                 d->d_GNext = d->d_MyGroup->sg_GBase;
800                                 d->d_MyGroup->sg_GBase = d;
801                         }
802                 } else {
803                         if (d->d_ScopeFlags & SCOPE_CONSTRUCTOR) {
804                                 d->d_CNext = d->d_MyGroup->sg_CBase;
805                                 d->d_MyGroup->sg_CBase = d;
806                         }
807                         if (d->d_ScopeFlags & SCOPE_DESTRUCTOR) {
808                                 d->d_DNext = d->d_MyGroup->sg_DBase;
809                                 d->d_MyGroup->sg_DBase = d;
810                         }
811                 }
812
813                 /*
814                  * If this procedure is bound to a DLL we have to resolve
815                  * it here.
816                  */
817                 if (d->d_ScopeFlags & SCOPE_CLANG) {
818                         d->d_ProcDecl.ed_DLLFunc = 
819                                 FindDLLSymbol(NULL, d->d_ImportSemGroup,
820                                               d->d_Id);
821                 }
822                 break;
823         case DOP_ARGS_STORAGE:
824         case DOP_STACK_STORAGE:
825         case DOP_GLOBAL_STORAGE:
826         case DOP_GROUP_STORAGE:
827                 type = resolveType(d->d_StorDecl.ed_Type);
828                 d->d_StorDecl.ed_Type = type;
829
830                 /*
831                  * Promote the lvalue storage qualifier (e.g. from a typedef)
832                  * into the declaration's scope.  This is what ultimately
833                  * controls lvalue vs rvalue arguments to procedures and such.
834                  */
835                 if ((type->ty_SQFlags & SF_LVALUE) && 
836                     (d->d_ScopeFlags & SCOPE_LVALUE) == 0
837                 ) {
838                         d->d_ScopeFlags |= SCOPE_LVALUE;
839                 }
840
841                 /*
842                  * Default assignment handling expects an rvalue.
843                  */
844                 if (d->d_StorDecl.ed_AssExp) {
845                         d->d_StorDecl.ed_AssExp =
846                                 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
847                                            d->d_StorDecl.ed_AssExp,
848                                            DEL_LVALUE(type), 1);
849                 }
850                 if (d->d_ScopeFlags & SCOPE_LVALUE) {
851                         /*
852                          * Object is passed as a LValueStor structure.  Note
853                          * that d_Bytes is going to be different then the
854                          * underlying type (which represents the actual
855                          * object).
856                          */
857                         d->d_Bytes = sizeof(LValueStor);
858                         d->d_AlignMask = LVALUE_ALIGN;
859                 } else { 
860                         /*
861                          * Object is passed by value.
862                          */
863                         d->d_AlignMask = type->ty_AlignMask;
864                         d->d_Bytes = type->ty_Bytes;
865                 }
866
867                 /*
868                  * If the declaration represents or contains an
869                  * argument-lvalue or a pointer we have to add it to
870                  * the SemGroup's SRBase list to properly reference or
871                  * dereference the elements.  XXX only do this for non-global
872                  * storage.
873                  *
874                  * If the declaration has LVALUE scope we must do the same
875                  * because the ref is tracked.
876                  */
877                 if (d->d_Op != DOP_GLOBAL_STORAGE &&
878                     (type->ty_Flags & TF_HASLVPTR)) {
879                         d->d_SRNext = d->d_MyGroup->sg_SRBase;
880                         d->d_MyGroup->sg_SRBase = d;
881                 } else if (d->d_ScopeFlags & SCOPE_LVALUE) {
882                         d->d_SRNext = d->d_MyGroup->sg_SRBase;
883                         d->d_MyGroup->sg_SRBase = d;
884                 }
885
886                 /*
887                  * Deal with constructor/destructor chaining.  The chaining
888                  * winds up being reversed and will be corrected by the
889                  * caller.
890                  */
891                 if (type->ty_Flags & TF_HASCONSTRUCT) {
892                         d->d_CNext = d->d_MyGroup->sg_CBase;
893                         d->d_MyGroup->sg_CBase = d;
894                 }
895                 if (type->ty_Flags & TF_HASDESTRUCT) {
896                         d->d_DNext = d->d_MyGroup->sg_DBase;
897                         d->d_MyGroup->sg_DBase = d;
898                 }
899                 if (type->ty_Flags & (TF_HASGCONSTRUCT|TF_HASGDESTRUCT)) {
900                         d->d_GNext = d->d_MyGroup->sg_GBase;
901                         d->d_MyGroup->sg_GBase = d;
902                 }
903                 break;
904         default:
905                 dassert_decl(d, 0);
906         }
907         d->d_Flags &= ~DF_RESOLVING;
908         d->d_Flags |= DF_RESOLVED;
909
910         /*
911          * Post resolution flag resolving (to handle recursion)
912          */
913         switch(d->d_Op) {
914         case DOP_PROC:
915                 /*
916                  * Create copies of procedures as they are needed (thus
917                  * avoiding an XxY matrix effect).
918                  */
919                 if ((st = d->d_ProcDecl.ed_OrigBody) == NULL) {
920                         Declaration *super = d->d_Super;
921                         while (super && super->d_ProcDecl.ed_OrigBody == NULL) {
922                                 super = super->d_Super;
923                         }
924                         if (super) {
925                                 st = super->d_ProcDecl.ed_OrigBody;
926                                 if (super->d_MyGroup->sg_Stmt->st_Op == ST_Class) {
927                                         /*
928                                          * Copy-down a procedure from a
929                                          * superclass.  The procedure must
930                                          * still be linked into its superclass
931                                          * for semantic searches to work as
932                                          * expected, hence the use of super->
933                                          * d_MyGroup and st->st_Parent.
934                                          *
935                                          * Note that this code is not reached
936                                          * in the case of a nested procedure,
937                                          * since nested procedures are copied
938                                          * with the parent.
939                                          */
940                                         st = DupStmt(super->d_MyGroup,
941                                                      st->st_Parent, st);
942                                 } else {
943                                         /*
944                                          * Copy-down a nested procedure.
945                                          * The procedure must be linked
946                                          * into the copy of the parent
947                                          * prodedure, not the original
948                                          * parent procedure, or it will
949                                          * never be resolved.
950                                          */
951                                         st = DupStmt(d->d_Stmt->st_MyGroup,
952                                                      d->d_Stmt, st);
953                                 }
954                         } else {
955                                 /*
956                                  * Internal procedure (we do not need to do
957                                  * anything), there is no statement body
958                                  * to duplicate.
959                                  */
960                         }
961                 } else {
962                         /*
963                          * Procedure is being used in the primary class it
964                          * was defined in.
965                          */
966                         st = DupStmt(d->d_MyGroup, st->st_Parent, st);
967                 }
968                 if (st) {
969                         /*
970                          * Link the procedure body to the declaration and
971                          * resolve the procedure body.
972                          */
973                         dassert_stmt(st, d->d_ProcDecl.ed_ProcBody == NULL);
974                         d->d_ProcDecl.ed_ProcBody = st;
975                         st->st_ProcStmt.es_Decl = d;
976                         st->st_ProcStmt.es_Scope = d->d_Scope;
977                         ResolveTypes(d->d_ImportSemGroup, st);
978                 }
979                 break;
980         default:
981                 break;
982         }
983
984         /*
985          * __align(%d) scope qualifier, override the type's alignment
986          */
987         if ((d->d_Scope.s_Flags & SCOPE_ALIGN) && d->d_Scope.s_AlignOverride)
988                 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
989 }
990
991 /*
992  * resolveExp() - resolve expression
993  *
994  * Resolve an expression.  We are expected to resolve all ex_Type's 
995  * for the expression tree as well as expected to track down
996  * operators and base identifiers.
997  *
998  * itype is a type hint.  If non-NULL, the caller would like our
999  * expression to return the specified type.  There are a few special
1000  * cases:
1001  *
1002  * EXF_REQ_ARRAY - when OBRACKET requests an arry optimization it
1003  *                 passes a post-array-indexed typehint (as if
1004  *                 you had done the optimization).  You must ignore
1005  *                 itype if you are unable to do the optimization.
1006  *
1007  * NOTE: Even rvalues may have refstor side-effects at run-time.
1008  */
1009 Exp *
1010 resolveExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int autocast)
1011 {
1012         Exp copy;
1013
1014         loadExpCopy(&copy, exp);
1015
1016         /*
1017          * note: certain cases below call other resolver functions and assume
1018          * that ex* variables are unchanged.
1019          */
1020
1021         dassert((exFlags & EXF_DUPEXP) || (exFlags & EXF_RESOLVED) == 0);
1022
1023         switch(exToken) {
1024         case TOK_ASS:
1025                 /*
1026                  * An assignment.  Note that we optimize void returns
1027                  * (such as when an assignment is a statement like 'a = 4;'
1028                  * ... the result of the assignment is cast to void.
1029                  *
1030                  * NOTE: Left-hand-side must be an LVALUE, return type
1031                  *       inherits this feature unless the parent turns off
1032                  *       the bit so the TOK_ASS run-time must deal with that.
1033                  */
1034                 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1035                 dassert_exp(exLhs, exLhs->ex_Type->ty_SQFlags & SF_LVALUE);
1036                 exRhs = resolveExp(isg, sg, exRhs,
1037                                    DEL_LVALUE(exLhs->ex_Type), 1);
1038
1039                 /* AssExp handles this optimization */
1040                 if (itype == &VoidType) {
1041                         exType = itype;
1042                         exFlags |= EXF_RET_VOID;
1043                 } else {
1044                         exType = exLhs->ex_Type;
1045                 }
1046
1047 #if 0
1048                 /*
1049                  * Check @ref assignment compatibility.
1050                  */
1051                 if (exLhs->ex_Type->ty_Op == TY_REFTO) {
1052                         switch(MatchType(exLhs->ex_Type, exRhs->ex_Type)) {
1053                         case SG_COMPAT_FULL:
1054                                 printf("assign %s compatibility FULL\n",
1055                                         exLhs->ex_Id);
1056                                 break;
1057                         case SG_COMPAT_PART:
1058                                 printf("assign %s compatibility PART\n",
1059                                         exLhs->ex_Id);
1060                                 break;
1061                         case SG_COMPAT_SUBCLASS:
1062                                 printf("assign %s compatibility SUBCL\n",
1063                                         exLhs->ex_Id);
1064                                 break;
1065                         case SG_COMPAT_FAIL:
1066                                 printf("assign %s compatibility FAIL\n",
1067                                         exLhs->ex_Id);
1068                                 break;
1069                         }
1070                 }
1071 #endif
1072                 break;
1073         case TOK_ANDAND:
1074                 /*
1075                  * NOTE: BoolType global implies an rvalue.
1076                  */
1077                 exLhs = resolveExp(isg, sg, exLhs, &BoolType, 1);
1078                 exRhs = resolveExp(isg, sg, exRhs, &BoolType, 1);
1079                 exType = &BoolType;
1080                 break;
1081         case TOK_OROR:
1082                 /*
1083                  * NOTE: BoolType global implies an rvalue.
1084                  */
1085                 exLhs = resolveExp(isg, sg, exLhs, &BoolType, 1);
1086                 exRhs = resolveExp(isg, sg, exRhs, &BoolType, 1);
1087                 exType = &BoolType;
1088                 break;
1089         case TOK_DECL:
1090                 /*
1091                  * This synthesized token occurs when we are able to collapse
1092                  * a structural indirection or dotted element into a
1093                  * declaration.  For example, 'module.routine'.
1094                  */
1095                 break;
1096         case TOK_DOT:
1097         case TOK_STRIND:
1098                 /*
1099                  * Structual field access.  The left hand side may be an object
1100                  * (class or compound), a class type, or a compound type.
1101                  * 
1102                  * A dotted access requires an lvalue on the left hand side
1103                  * if the left hand side represents storage.
1104                  *
1105                  * The result will be an lvalue if the right hand side
1106                  * represents storage.  We only loop if the right hand side
1107                  * is an alias replacement.
1108                  */
1109                 {
1110                         string_t id;
1111                         Declaration *d;
1112                         SemGroup *sg2;
1113                         Type *type;
1114                         int globalOnly = 0;
1115                         int s;
1116                         int visibility;
1117                         int isRefTo = 0;
1118                         int procedureOnly = 0;
1119                         int eno = TOK_ERR_ID_NOT_FOUND;
1120
1121                         /*
1122                          * NOTE: Hint must 'always happen' since we may be
1123                          *       modifying an expression that will later be
1124                          *       Dup'd.
1125                          *
1126                          * NOTE: Lhs is always an lvalue for TOK_DOT, but
1127                          *       does not have to be for TOK_STRIND.
1128                          */
1129                         exLhs->ex_Flags |= EXF_REQ_TYPE;
1130                         exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1131
1132                         /*
1133                          * The RHS may have been turned into a TOK_SEMGRP_ID
1134                          * in a previous duplicate.  The change is considered
1135                          * permanent.
1136                          */
1137                         if (exRhs->ex_Token != TOK_SEMGRP_ID) {
1138                                 dassert_exp(exRhs,
1139                                             exRhs->ex_Token == TOK_STRUCT_ID);
1140                                 exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
1141                         }
1142                         id = exRhs->ex_Id;
1143                         type = exLhs->ex_Type;
1144
1145                         /*
1146                          * Calculate scope and SemGroup to search.  Note
1147                          * that it is legal to do a structural '.' selection
1148                          * on a pointer, but it works differently then
1149                          * indirecting through a pointer via '->'.  In the
1150                          * case of '.' on a pointer, we first search the
1151                          * system Pointer class.
1152                          */
1153                         if (exLhs->ex_Flags & EXF_RET_TYPE) {
1154                                 globalOnly = 1;
1155                         }
1156
1157                         /*
1158                          * Figure out the base type used to look-up the
1159                          * identifier.  An identifier that resolves into a
1160                          * procedure winds up only being a hint for a
1161                          * reference type.
1162                          */
1163                         if (exToken == TOK_STRIND) {
1164                                 switch(type->ty_Op) {
1165                                 case TY_CPTRTO:
1166                                         type = type->ty_CPtrType.et_Type;
1167                                         break;
1168                                 case TY_PTRTO:
1169                                         type = type->ty_PtrType.et_Type;
1170                                         break;
1171                                 case TY_REFTO:
1172                                         type = type->ty_RefType.et_Type;
1173                                         isRefTo = 1;
1174                                         break;
1175                                 default:
1176                                         dassert_exp(exp, 0);
1177                                         /* not reached */
1178                                 }
1179                         }
1180
1181 again:
1182                         switch(type->ty_Op) {
1183                         case TY_CLASS:
1184                                 sg2 = type->ty_ClassType.et_SemGroup;
1185                                 break;
1186                         case TY_COMPOUND:
1187                                 sg2 = type->ty_CompType.et_SemGroup;
1188                                 break;
1189                         case TY_ARGS:
1190                                 sg2 = type->ty_ArgsType.et_SemGroup;
1191                                 break;
1192                         case TY_VAR:
1193                                 sg2 = type->ty_VarType.et_SemGroup;
1194                                 break;
1195                         case TY_IMPORT:
1196                                 sg2 = type->ty_ImportType.et_SemGroup;
1197                                 break;
1198                         case TY_CPTRTO:
1199                                 /* YYY */
1200                                 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1201                                 sg2 = PointerType.ty_ClassType.et_SemGroup;
1202                                 break;
1203                         case TY_PTRTO:
1204                                 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1205                                 sg2 = PointerType.ty_ClassType.et_SemGroup;
1206                                 break;
1207                         case TY_REFTO:
1208                                 /* YYY */
1209                                 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1210                                 sg2 = PointerType.ty_ClassType.et_SemGroup;
1211                                 break;
1212                         default:
1213                                 /*
1214                                  * Possibly a pointer, aka ptr.NULL
1215                                  */
1216                                 sg2 = NULL;
1217                         }
1218                         visibility = exLhs->ex_Visibility;
1219
1220                         /*
1221                          * Locate the identifier normally, via its type.
1222                          * ty_TypeVisbility is the initial visibility (scope)
1223                          * that the semantic search should use in locating
1224                          * the identifier.
1225                          */
1226                         if (sg2) {
1227                                 string_t ary[2] = { id, NULL };
1228                                 int level;
1229
1230                                 if (exLhs->ex_Token == TOK_ID ||
1231                                     exLhs->ex_Token == TOK_DECL) {
1232                                         if (exLhs->ex_Decl->d_Search) {
1233                                                 level = exLhs->ex_Decl->
1234                                                          d_Search->sg_Level;
1235                                         } else {
1236                                                 level = sg2->sg_Level;
1237                                         }
1238
1239                                         /*
1240                                          * XXX BIG HACK
1241                                          */
1242                                         if (exLhs->ex_Flags & EXF_SUPER) {
1243                                                 if (isRefTo) {
1244                                                         fprintf(stderr, "Can't super with reference type\n");
1245                                                         dassert_exp(exp, 0);
1246                                                 }
1247                                                 if (level == 0) {
1248                                                         fprintf(stderr, "No superclass available\n");
1249                                                         dassert_exp(exp, 0);
1250                                                 }
1251                                                 --level;
1252                                         }
1253                                 } else {
1254                                         level = sg2->sg_Level;  /* may be -1 */
1255                                 }
1256                                 visibility &= type->ty_Visibility;
1257                                 d = FindDeclPath(&exp->ex_LexRef, NULL,
1258                                                  sg2, NULL,
1259                                                  ary, FDC_NOBACK,
1260                                                  &visibility, level, &eno);
1261                                 /*
1262                                  * XXX more hack.  If the super is visible
1263                                  * and a procedure we just found our own
1264                                  * refinement, not the superclass method.
1265                                  * This is because there is no 'superclass
1266                                  * method' per say, refinements *REPLACE*
1267                                  * superclass declarations and inherit the
1268                                  * superclass's level.  However, we still
1269                                  * want to be able to chain method calls so
1270                                  * what we do instead is go through and find
1271                                  * the procedure that we smacked when we did
1272                                  * the refinement.  This procedure has
1273                                  * already been conveniently brought into
1274                                  * the subclass context as an 'invisible'
1275                                  * entity at the same d_Level.
1276                                  */
1277                                 if ((exLhs->ex_Flags & EXF_SUPER) &&
1278                                     d &&
1279                                     d->d_Op == DOP_PROC &&
1280                                     (d->d_ScopeFlags & SCOPE_ALL_VISIBLE)
1281                                 ) {
1282                                         string_t id2 = d->d_Id;
1283                                         SemGroup *olevel = d->d_Level;
1284
1285                                         dassert_exp(exp, isRefTo == 0);
1286
1287                                         while ((d = getSucc(&d->d_MyGroup->sg_DeclList, &d->d_Node)) != NULL) {
1288                                                 if (d->d_Id == id2 &&
1289                                                     d->d_Level == olevel && 
1290                                                     d->d_Op == DOP_PROC) {
1291                                                         break;
1292                                                 }
1293                                         }
1294                                 }
1295                         } else {
1296                                 d = NULL;
1297                         }
1298
1299                         if (d && procedureOnly && d->d_Op != DOP_PROC) {
1300                                 fprintf(stderr,
1301                                         "PTR.ELEMENT may be used for special "
1302                                         "pointer method calls, but not to "
1303                                         "access storage elements.  "
1304                                         "Use PTR->ELEMENT instead\n");
1305                                 dassert_exp(exp, 0);
1306                         }
1307
1308                         /*
1309                          * If referencing actual storage the storage must be
1310                          * declared global.
1311                          */
1312                         if (d && globalOnly && (d->d_Op & DOPF_STORAGE) &&
1313                                 (d->d_ScopeFlags & SCOPE_GLOBAL) == 0
1314                         ) {
1315                                 fprintf(stderr,
1316                                         "%s is not global.  Only globals "
1317                                         "can be accessed through a type\n",
1318                                         d->d_Id);
1319                                 dassert_exp(exp, 0);
1320                         }
1321
1322                         if (d) {
1323                                 /*
1324                                  * Identifier found.  Note that if we are
1325                                  * going through a reference type the
1326                                  * declaration is not the actual one we 
1327                                  * use at run time.  It's just a template.
1328                                  */
1329                                 resolveDecl(d);
1330                                 exDecl = d;
1331                                 exVisibility = visibility;
1332
1333                                 switch(d->d_Op) {
1334                                 case DOP_PROC:
1335                                         exType = d->d_ProcDecl.ed_Type;
1336                                         if (d->d_ProcDecl.ed_Type->ty_SQFlags & SF_METHOD) {
1337                                                 /*
1338                                                  * Method call, do not
1339                                                  * collapse the expression into
1340                                                  * a direct declaration because
1341                                                  * the object is needed later.
1342                                                  */
1343                                                 if (exLhs->ex_Flags & EXF_RET_TYPE)
1344                                                         ExpPrintError(exLhs, TOK_ERR_METHOD_REQUIRES_OBJ);
1345                                                 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1346                                         } else if (isRefTo) {
1347                                                 /*
1348                                                  * Call via reference.  The
1349                                                  * lhs is required to evaluate
1350                                                  * the actual method call at
1351                                                  * run-time.
1352                                                  */
1353                                         } else {
1354                                                 /*
1355                                                  * Global method call or normal
1356                                                  * call.  For the global method
1357                                                  * case the lhs is not needed
1358                                                  * because the parser entered
1359                                                  * the first argument as a
1360                                                  * type already.
1361                                                  *
1362                                                  * Degenerate into a TOK_DECL.
1363                                                  * We depend on this later.
1364                                                  */
1365                                                 exFlags &= ~EXF_BINARY;
1366                                                 exLhs = NULL;
1367                                                 exRhs = NULL;
1368                                                 exToken = TOK_DECL;
1369                                         }
1370                                         break;
1371                                 case DOP_ALIAS:
1372                                         exType = DEL_LVALUE(d->d_AliasDecl.ed_Type);
1373                                         dassert_decl(d, d->d_AliasDecl.ed_AssExp != NULL);
1374                                         /*
1375                                          * NOTE: exLhs must be NULL if exp is
1376                                          * unresolved.  exp tree duplications
1377                                          * do not duplicate the alias's exLHS
1378                                          * even though UNARY is set.
1379                                          */
1380                                         dassert_exp(exp, exRhs->ex_Lhs == NULL);
1381                                         exRhs->ex_Flags |= EXF_ALIAS | EXF_UNARY;
1382                                         exRhs->ex_Lhs = DupExp(sg2,
1383                                                            d->d_AliasDecl.ed_AssExp);
1384                                         exRhs->ex_Lhs = resolveExp(isg, sg2,
1385                                                                 exRhs->ex_Lhs,
1386                                                                 exType, 1);
1387                                         break;
1388                                 case DOP_ARGS_STORAGE:
1389                                 case DOP_STACK_STORAGE:
1390                                 case DOP_GLOBAL_STORAGE:
1391                                 case DOP_GROUP_STORAGE:
1392                                         /*
1393                                          * Set type.  The Rhs is a STRUCT_ID
1394                                          * and does not require a type to be
1395                                          * assigned to it.
1396                                          *
1397                                          * Return type is always an LVALUE,
1398                                          * parent may adjust.
1399                                          */
1400                                         exType = ADD_LVALUE(d->d_StorDecl.ed_Type);
1401                                         break;
1402                                 case DOP_TYPEDEF:
1403                                         /*
1404                                          * XXX make sure this is only used
1405                                          * in the lhs of a structural
1406                                          * reference. XXX
1407                                          *
1408                                          * XXX what if we went through a
1409                                          * TY_RETO type?  This type will
1410                                          * be wrong.
1411                                          *
1412                                          * collapse the exp node.
1413                                          */
1414                                         exType = d->d_TypedefDecl.ed_Type;
1415                                         exToken = TOK_DECL;
1416                                         exFlags &= ~EXF_BINARY;
1417                                         break;
1418                                 case DOP_IMPORT:
1419                                         /*
1420                                          * Do not collapse an import, we
1421                                          * require more resolution.  e.g.
1422                                          * import.<blah> will be collapsed,
1423                                          * but 'import' cannot be.
1424                                          */
1425                                         if (exFlags & EXF_REQ_TYPE) {
1426                                                 exType =
1427                         AllocImportType(
1428                                 &d->d_ImportDecl.ed_SemGroup->sg_ClassList,
1429                                 d->d_ImportDecl.ed_SemGroup,
1430                                 visibility);
1431                                                 exFlags |= EXF_RET_TYPE;
1432                                                 break;
1433                                         }
1434                                         break;
1435                                 case DOP_CLASS:
1436                                         /*
1437                                          * Do not collapse a class, we require
1438                                          * more resolution.  e.g. class.<blah>
1439                                          * will be collapsed, but 'class'
1440                                          * cannot be.
1441                                          */
1442                                         if (exFlags & EXF_REQ_TYPE) {
1443                                                 exType =
1444                         AllocClassType(
1445                                 &d->d_ClassDecl.ed_SemGroup->sg_ClassList,
1446                                 d->d_ClassDecl.ed_Super,
1447                                 d->d_ClassDecl.ed_SemGroup,
1448                                 visibility);
1449                                                 exFlags |= EXF_RET_TYPE;
1450                                                 break;
1451                                         }
1452                                         break;
1453                                 default:
1454                                         dassert_exp(exp, 0);
1455                                         break;
1456                                 }
1457                         } else if ((s = StrTableSpecial(id)) &
1458                                    SPECIALF_SEMGROUP) {
1459                                 /*
1460                                  * Identifier not found, check for a special
1461                                  * identifier.
1462                                  */
1463                                 exRhs->ex_Token = TOK_SEMGRP_ID;
1464                                 exRhs->ex_Int32 = s;
1465                                 exDecl = NULL;
1466
1467                                 switch(s) {
1468                                 case SPECIAL_NULL:
1469                                         dassert(type->ty_Op == TY_PTRTO || 
1470                                                 type->ty_Op == TY_REFTO ||
1471                                                 type->ty_Op == TY_CPTRTO);
1472                                         /* NULL is not an lvalue */
1473                                         exType = DEL_LVALUE(type);
1474                                         exFlags |= EXF_NULL;
1475                                         break;
1476                                 case SPECIAL_COUNT:
1477                                         dassert(type->ty_Op != TY_PTRTO && 
1478                                                 type->ty_Op != TY_REFTO &&
1479                                                 type->ty_Op != TY_CPTRTO);
1480                                         exType = &Int32Type;
1481                                         break;
1482                                 case SPECIAL_DATA:
1483                                         /*
1484                                          * typeof(self.__data[]) vs
1485                                          * (cast)self.__data[]
1486                                          */
1487                                         dassert(type->ty_Op != TY_PTRTO &&
1488                                                 type->ty_Op != TY_REFTO &&
1489                                                 type->ty_Op != TY_CPTRTO);
1490                                         dassert(exFlags & EXF_REQ_ARRAY);
1491                                         exFlags |= EXF_RET_ARRAY;
1492                                         if (exFlags & EXF_REQ_TYPE) {
1493                                                 exFlags |= EXF_RET_TYPE;
1494                                                 exType = &DynamicLValueType;
1495                                         } else if (itype) {
1496                                                 exType = itype;
1497                                         } else {
1498                                                 /*
1499                                                  * dynamic data must be cast
1500                                                  */
1501                                                 dassert_exp(exp, 0);
1502                                                 exType = &DynamicLValueType;
1503                                         }
1504                                         break;
1505                                 case SPECIAL_VAR_COUNT:
1506                                         dassert(type->ty_Op != TY_PTRTO &&
1507                                                 type->ty_Op != TY_REFTO &&
1508                                                 type->ty_Op != TY_CPTRTO);
1509                                         exType = &Int32Type;
1510                                         break;
1511                                 case SPECIAL_VAR_DATA:
1512                                         /*
1513                                          * typeof(self.__vardata[]) vs
1514                                          * (cast)self.__vardata[]
1515                                          */
1516                                         dassert(type->ty_Op != TY_PTRTO &&
1517                                                 type->ty_Op != TY_REFTO &&
1518                                                 type->ty_Op != TY_CPTRTO);
1519                                         dassert(exFlags & EXF_REQ_ARRAY);
1520                                         exFlags |= EXF_RET_ARRAY;
1521                                         if (exFlags & EXF_REQ_TYPE) {
1522                                                 exFlags |= EXF_RET_TYPE;
1523                                                 exType = &DynamicLValueType;
1524                                         } else if (itype) {
1525                                                 exType = itype;
1526                                         } else {
1527                                                 /*
1528                                                  * dynamic data must be cast
1529                                                  */
1530                                                 dassert_exp(exp, 0);
1531                                                 exType = &DynamicLValueType;
1532                                         }
1533                                         break;
1534                                 case SPECIAL_TYPEID:
1535                                         exType = &Int32Type;
1536                                         break;
1537                                 case SPECIAL_TYPESTR:
1538                                         exType = &StrType;
1539                                         break;
1540                                 default:
1541                                         dassert_exp(exRhs, 0);
1542                                         break;
1543                                 }
1544                         } else {
1545                                 /*
1546                                  * This is nasty, I admit.  If we have a
1547                                  * pointer or reference type try again.
1548                                  */
1549                                 exDecl = NULL;
1550                                 if (type->ty_Op == TY_PTRTO) {
1551                                         type = type->ty_PtrType.et_Type;
1552                                         procedureOnly = 1;
1553                                         goto again;
1554                                 }
1555                                 if (type->ty_Op == TY_REFTO) {
1556                                         type = type->ty_RefType.et_Type;
1557                                         procedureOnly = 1;
1558                                         goto again;
1559                                 }
1560                                 if (type->ty_Op == TY_CPTRTO) {
1561                                         type = type->ty_CPtrType.et_Type;
1562                                         procedureOnly = 1;
1563                                         goto again;
1564                                 }
1565                                 ExpPrintError(exRhs, eno);
1566                                 dassert(0);
1567                         }
1568                 }
1569                 dassert_exp(exp, exType != NULL);
1570                 break;
1571         case TOK_STRUCT_ID:
1572                 /*
1573                  * NOTE: unresolved identifiers should not have alias
1574                  *       expression sub-tree duplications attached to them.
1575                  *       assert it.
1576                  */
1577                 dassert_exp(exp, exLhs == NULL);
1578                 break;
1579         case TOK_OPER:
1580                 /*
1581                  * NOTE: LVALUE/RVALUE for elements and return type depends
1582                  *       on the operator.  Operator functions normally
1583                  *       self-optimize the cases at run-time.
1584                  */
1585                 saveExpCopy(&copy, exp);
1586                 exp = resolveExpOper(isg, sg, exp, itype);
1587                 loadExpCopy(&copy, exp);
1588                 break;
1589         case TOK_PTRIND:
1590                 /*
1591                  * Indirect through an expression.
1592                  *
1593                  * Return type is typically an LVALUE (if representing
1594                  * storage).  Exp parent might turn it off so run-time
1595                  * must test.  Lhs may or may not be.
1596                  */
1597                 {
1598                         Type *type;
1599
1600                         exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1601                         type = exLhs->ex_Type;
1602
1603                         switch(type->ty_Op) {
1604                         case TY_REFTO:
1605                                 if ((exFlags & EXF_INDREF) == 0) {
1606                                         fprintf(stderr, "You cannot use '*' on a reference type\n");
1607                                         dassert_exp(exLhs, 0);
1608                                 }
1609                                 exType = ADD_LVALUE(type->ty_RefType.et_Type);
1610                                 break;
1611                         case TY_PTRTO:
1612                                 exType = ADD_LVALUE(type->ty_PtrType.et_Type);
1613                                 break;
1614                         case TY_CPTRTO:
1615                                 exType = ADD_LVALUE(type->ty_CPtrType.et_Type);
1616                                 break;
1617                         default:
1618                                 dassert_exp(exLhs, 0);
1619                                 break;
1620                         }
1621                 }
1622                 break;
1623         case TOK_ADDR:
1624                 /*
1625                  * Take the address of an (LVALUE) expression.  Returns an
1626                  * RVALUE.   Allow for a short-cut optimization which replaces
1627                  * the TOK_ADDR sequence with its argument in the &ary[n]
1628                  * case.
1629                  */
1630                 {
1631                         Type *type;
1632
1633                         /*
1634                          * note: hint must 'always happen' since we may be
1635                          * modifying an expression that will later be Dup'd.
1636                          */
1637                         exLhs->ex_Flags |= EXF_REQ_ADDROF;
1638                         exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1639                         if (exLhs->ex_Flags & EXF_RET_ADDROF) {
1640                                 exp = exLhs;
1641                                 loadExpCopy(&copy, exp);
1642                         } else {
1643                                 type = exLhs->ex_Type;
1644                                 dassert_exp(exLhs,
1645                                             type->ty_SQFlags & SF_LVALUE);
1646                                 exType = resolveType(TypeToPtrType(type));
1647                                 /* DEL_LVALUE() not needed here */
1648                         }
1649                 }
1650                 break;
1651         case TOK_OBRACKET:
1652                 /*
1653                  * Array index, takes an RVALUE, returns an LVALUE.
1654                  *
1655                  * Note: we have to convert the special __data[exp] case.
1656                  *
1657                  * Note: ex_Flags hints must 'always happen' since we may be
1658                  *       modifying an expression that will later be Dup'd.
1659                  */
1660                 exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
1661                 exLhs->ex_Flags |= EXF_REQ_ARRAY | (exFlags & EXF_REQ_TYPE);
1662                 exLhs->ex_AuxExp = exRhs;
1663                 exLhs = resolveExp(isg, sg, exLhs, itype, 0);
1664
1665                 if (MatchType(&IntegralType, exRhs->ex_Type) <= SG_COMPAT_PART) {
1666                         ExpPrintError(exRhs, TOK_ERR_EXPECTED_INTEGRAL_TYPE);
1667                         dassert_exp(exp, 0);
1668                 }
1669
1670                 if (exLhs->ex_Flags & EXF_RET_ARRAY) {
1671                         /*
1672                          * __data and __vardata specials
1673                          */
1674                         exp->ex_Token = TOK_ERR_EXP_REMOVED;
1675                         return(exLhs);
1676                 } else if (exFlags & EXF_REQ_ADDROF) {
1677                         /*
1678                          * &ary[i] optimization - allows us to create
1679                          * a bounded pointer (returns an RVALUE).
1680                          */
1681                         Type *type;
1682
1683                         exFlags |= EXF_RET_ADDROF;
1684
1685                         dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1686
1687                         exLhs->ex_AuxExp = NULL;
1688                         type = exLhs->ex_Type;
1689                         switch(type->ty_Op) {
1690                         case TY_ARYOF:
1691                                 type = type->ty_AryType.et_Type;
1692                                 break;
1693                         case TY_CPTRTO:
1694                                 type = type->ty_CPtrType.et_Type;
1695                                 break;
1696                         case TY_PTRTO:
1697                                 type = type->ty_PtrType.et_Type;
1698                                 break;
1699                         case TY_REFTO:
1700                                 /* Cannot take address of a reference type */
1701                                 dassert_exp(exp, 0);
1702                                 break;
1703                         }
1704                         exType = resolveType(TypeToPtrType(type));
1705                         /* returns an RVALUE */
1706                 } else {
1707                         /*
1708                          * Unoptimized array lookup, returns an lvalue
1709                          */
1710                         Type *type;
1711
1712                         dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1713
1714                         exLhs->ex_AuxExp = NULL;
1715                         type = exLhs->ex_Type;
1716                         switch(type->ty_Op) {
1717                         case TY_ARYOF:
1718                                 type = type->ty_AryType.et_Type;
1719                                 break;
1720                         case TY_CPTRTO:
1721                                 type = type->ty_CPtrType.et_Type;
1722                                 break;
1723                         case TY_PTRTO:
1724                                 type = type->ty_PtrType.et_Type;
1725                                 break;
1726                         case TY_REFTO:
1727                                 fprintf(stderr,
1728                                         "Cannot index a reference type\n");
1729                                 dassert_exp(exp, 0);
1730                                 break;
1731                         }
1732                         exType = ADD_LVALUE(type);
1733                         /* returns an LVALUE */
1734                 }
1735                 break;
1736         case TOK_OPAREN:
1737                 dassert_exp(exp, 0);    /* XXX */
1738                 break;
1739         case TOK_DSTRING:
1740                 /*
1741                  * XXX we should return a bounded pointer here.
1742                  */
1743                 exType = &StrType;
1744                 exId = StrTableEscapeQuotedString(exId, strlen(exId), 1);
1745                 ReplaceStrTable(&exp->ex_Id, exId);
1746                 break;
1747         case TOK_SSTRING:
1748                 exType = &CharType;
1749                 exId = StrTableEscapeQuotedString(exId, strlen(exId), 0);
1750                 dassert(StrTableLen(exId) == 1);
1751                 ReplaceStrTable(&exp->ex_Id, exId);
1752                 break;
1753         case TOK_BSTRING:
1754                 /* reserved for inline execution or something else */
1755                 dassert_exp(exp, 0);    /* XXX */
1756                 break;
1757         case TOK_INTEGER:
1758                 {
1759                         char *ptr;
1760
1761                         strtol(exp->ex_Id, &ptr, 0);
1762                         if (*ptr == '.') {
1763                                 int doUnsigned = 0;
1764
1765                                 ++ptr;
1766                                 if (*ptr == 'U') {
1767                                         ++ptr;
1768                                         doUnsigned = 1;
1769                                         exFlags |= EXF_UNSIGNED;
1770                                 } 
1771                                 if (*ptr == 'B') {
1772                                         exType = (doUnsigned) ? &UInt8Type :
1773                                                                 &Int8Type;
1774                                 } else if (*ptr == 'W') {
1775                                         exType = (doUnsigned) ? &UInt16Type :
1776                                                                 &Int16Type;
1777                                 } else if (*ptr == 'L') {
1778                                         exType = (doUnsigned) ? &UInt64Type :
1779                                                                 &Int64Type;
1780                                 } else if (*ptr == 0) {
1781                                         exType = (doUnsigned) ? &UInt32Type :
1782                                                                 &Int32Type;
1783                                 } else {
1784                                         dassert_exp(exp, 0);
1785                                 }
1786                         } else {
1787                                 exType = &Int32Type;
1788                         }
1789                 }
1790                 break;
1791         case TOK_FLOAT:
1792                 {
1793                         char *ptr;
1794
1795                         strtod(exp->ex_Id, &ptr);
1796                         if (*ptr == '.') {
1797                                 ++ptr;
1798                                 if (*ptr == 'F') {
1799                                         exType = &Float32Type;
1800                                 } else if (*ptr == 'D') {
1801                                         exType = &Float64Type;
1802                                 } else if (*ptr == 'X') {
1803                                         exType = &Float128Type;
1804                                 } else {
1805                                         dassert_exp(exp, 0);
1806                                 }
1807                         } else {
1808                                 exType = &Float64Type;
1809                         }
1810                 }
1811                 break;
1812         case TOK_VOIDEXP:
1813                 exType = &VoidType;
1814                 break;
1815         case TOK_SELF:
1816                 /*
1817                  * The self identifier represents the current procedure's
1818                  * arguments.  A varargs procedure will actually be called
1819                  * with an extended version of this type, but for resolution
1820                  * purposes we can use this time.
1821                  *
1822                  * This is an LVALUE to support things like self.new() XXX.
1823                  */
1824                 exType = ADD_LVALUE(resolveArgsType(sg));
1825                 break;
1826         case TOK_DOLLAR:
1827                 /*
1828                  * The '$' identifier represents the current procedure's
1829                  * return storage.
1830                  */
1831                 exType = ADD_LVALUE(resolveReturnType(sg));
1832                 break;
1833         case TOK_ID:
1834         case TOK_CLASSID:
1835                 /*
1836                  * Lookup the identifier.  The returned declaration could 
1837                  * represent a class, typedef, module, or storage, but for
1838                  * this case we only allow storage or a constant.  Since
1839                  * we are starting from our own semantic group, visibility
1840                  * is initially ALL (private, library, and public).
1841                  *
1842                  * The identifier might represent something at a higher scoping
1843                  * layer.  For example, a nested procedure accessing a variable
1844                  * in the parent procedure or a method procedure in a class
1845                  * accessing an element of the object.
1846                  *
1847                  * This returns an LVALUE if the id represents storage.
1848                  */
1849                 {
1850                         string_t ary[2];
1851                         int eno = TOK_ERR_ID_NOT_FOUND;
1852
1853                         exDecl = NULL;
1854
1855                         /*
1856                          * Special case 'super'. XXX TY_REFTO
1857                          *
1858                          * Make an in-place change to the expression
1859                          * structure.  'super' is actually 'this' with the
1860                          * EXF_SUPER flag set.
1861                          */
1862                         if (exId == String_Super) {
1863                                 exId = String_This;
1864                                 ReplaceStrTable(&exp->ex_Id, exId);
1865                                 exFlags |= EXF_SUPER;
1866                         }
1867                         ary[0] = exp->ex_Id;
1868                         ary[1] = NULL;
1869
1870                         exDecl = FindDeclPath(&exp->ex_LexRef, isg, sg,
1871                                               NULL, ary,
1872                                               FDC_NULL, &exVisibility,
1873                                               -1, &eno);
1874                         if (exDecl == NULL) {
1875                                 ExpPrintError(exp, eno);
1876                                 dassert_exp(exp, 0);
1877                         }
1878                 }
1879                 switch(exDecl->d_Op) {
1880                 case DOP_ARGS_STORAGE:
1881                 case DOP_STACK_STORAGE:
1882                 case DOP_GLOBAL_STORAGE:
1883                 case DOP_GROUP_STORAGE:
1884                         /*
1885                          * Storage identifiers are lvalues.
1886                          */
1887                         exType = ADD_LVALUE(exDecl->d_StorDecl.ed_Type);
1888                         break;
1889                 case DOP_ALIAS:
1890                         /*
1891                          * Aliases are rvalues (even if they could be lvalues).
1892                          */
1893                         exType = DEL_LVALUE(exDecl->d_AliasDecl.ed_Type);
1894                         exFlags |= EXF_ALIAS | EXF_UNARY;
1895
1896                         /*
1897                          * NOTE: exLhs must be NULL if exp is unresolved.
1898                          *       exp tree duplications do not duplicate
1899                          *       the alias's exLHS even though UNARY is set.
1900                          */
1901                         dassert_exp(exp, exLhs == NULL);
1902                         exLhs = DupExp(sg, exDecl->d_AliasDecl.ed_AssExp);
1903                         exLhs = resolveExp(isg, sg, exLhs, exType, 1);
1904
1905                         /*
1906                          * Inherit EXF_NULL (NULL pointer special) through
1907                          * the alias, otherwise it will not be assignable
1908                          * to arbitrary pointers.
1909                          */
1910                         exFlags |= exLhs->ex_Flags & EXF_NULL;
1911                         break;
1912
1913                 case DOP_PROC:
1914                         /*
1915                          * A procedural identifier.
1916                          *
1917                          * Note: procedural pointers cannot be changed so
1918                          *       they are not lvalues.
1919                          */
1920                         dassert_exp(exp, (exFlags & EXF_REQ_PROC));
1921                         exType = exDecl->d_ProcDecl.ed_Type;
1922                         break;
1923                 case DOP_TYPEDEF:
1924                         if (exFlags & EXF_REQ_TYPE) {
1925                                 exType = exDecl->d_TypedefDecl.ed_Type;
1926                                 exFlags |= EXF_RET_TYPE;
1927                                 break;
1928                         }
1929                         dassert_exp(exp, 0);
1930                         break;
1931                 case DOP_CLASS:
1932                         if (exFlags & EXF_REQ_TYPE) {
1933                                 exType =
1934                     AllocClassType(
1935                             &exDecl->d_ClassDecl.ed_SemGroup->sg_ClassList,
1936                             exDecl->d_ClassDecl.ed_Super,
1937                             exDecl->d_ClassDecl.ed_SemGroup,
1938                             exVisibility);
1939                                 exFlags |= EXF_RET_TYPE;
1940                                 break;
1941                         }
1942                         dassert_exp(exp, 0);
1943                         break;
1944                 case DOP_IMPORT:
1945                         if (exFlags & EXF_REQ_TYPE) {
1946                                 exType =
1947                     AllocImportType(
1948                             &exDecl->d_ImportDecl.ed_SemGroup->sg_ClassList,
1949                             exDecl->d_ImportDecl.ed_SemGroup,
1950                             exVisibility);
1951                                 exFlags |= EXF_RET_TYPE;
1952                                 break;
1953                         }
1954                         dassert_exp(exp, 0);
1955                         break;
1956                 default:
1957                         dassert_exp(exp, 0);
1958                 }
1959                 break;
1960         case TOK_NOT:
1961                 /*
1962                  * NOTE: BoolType global implies an rvalue.
1963                  */
1964                 exLhs = resolveExp(isg, sg, exLhs, &BoolType, 1);
1965                 break;
1966         case TOK_TYPE:
1967                 if (exFlags & EXF_REQ_TYPE) {
1968                         exType = resolveType(exType);
1969                         exFlags |= EXF_RET_TYPE;
1970                 } else {
1971                         dassert_exp(exp, 0);
1972                 }
1973                 break;
1974         case TOK_CAST:
1975                 /*
1976                  * User cast (or maybe the parser inserted it).  Try to
1977                  * resolve the expression with the requested type hint
1978                  * but tell resolveExp() not to force the cast.
1979                  *
1980                  * Then check the result.  If resolveExp() was not able to
1981                  * optimize the requested cast then resolve the cast.
1982                  *
1983                  * If the types are compatible we still keep the TOK_CAST
1984                  * node in place for the moment.  XXX we really need to
1985                  * formalized how ex_Type is set Similar vs Exact.
1986                  *
1987                  * NOTE: Cast results are always an RVALUE.  XXX validate here.
1988                  */
1989                 if ((exFlags & EXF_PARSE_TYPE) == 0) {
1990                         exRhs->ex_Flags |= EXF_REQ_TYPE;
1991                         exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
1992                         exType = exRhs->ex_Type;
1993                 }
1994                 exLhs = resolveExp(isg, sg, exLhs, exType, 0);
1995                 if (SimilarType(exType, exLhs->ex_Type) == 0) {
1996                         saveExpCopy(&copy, exp);
1997                         exp = resolveExpCast(isg, sg, exLhs, exType);
1998                         loadExpCopy(&copy, exp);
1999                 }
2000 #if 0
2001                 /* propagate NULL flag to allow cast to any pointer type */
2002                 if (exLhs->ex_Flags & EXF_NULL)
2003                         printf("LHS NULL\n");
2004                 exp->ex_Flags |= exLhs->ex_Flags & EXF_NULL;
2005 #endif
2006                 break;
2007         case TOK_CALL:
2008                 /*
2009                  * Calls require the RHS to be a compound expression
2010                  * representing the procedure arguments.
2011                  *
2012                  * XXX deal with pointer-to-function verses function
2013                  * XXX the lhs must at the moment resolve to the procedure
2014                  * itself.
2015                  *
2016                  * In regards to procedure pointers, the declaration
2017                  * will require a pointer to the procedure's statement
2018                  * body.  XXX this pointer can be the physical storage
2019                  * associated with the lhs data but thus requires the
2020                  * type to be a pointer.  We do not support the 'C'
2021                  * (*ptr_to_func)(...) form.  You have to use ptr_to_func(...).
2022                  */
2023                 {
2024                         Type *ltype;
2025
2026                         dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2027
2028                         /*
2029                          * Note: ex_Flags hints must 'always happen' since
2030                          * we may be modifying an expression that will later
2031                          * be Dup'd.
2032                          */
2033                         exLhs->ex_Flags |= EXF_REQ_PROC;
2034                         exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2035                         ltype = exLhs->ex_Type;
2036 #if 0
2037                         if (ltype->ty_Op == TY_PTRTO)
2038                                 ltype = type->ty_PtrType.et_Type; /* XXX */
2039 #endif
2040 #if 0
2041                         dassert_exp(exLhs, exLhs->ex_Token == TOK_DECL ||
2042                                            exLhs->ex_Token == TOK_ID);
2043 #endif
2044                         dassert_exp(exLhs, ltype != NULL &&
2045                                            ltype->ty_Op == TY_PROC);
2046                         dassert_exp(exLhs, exLhs->ex_Decl != NULL);
2047                         dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2048
2049                         /*
2050                          * If the lhs type indicates a method procedure, then
2051                          * it's lhs is the object we wish to pass as the
2052                          * first argument to the method.  We move the lhs lhs
2053                          * exp.  For a STRIND TY_PTRTO method call we
2054                          * indirect the element and convert it to a TOK_DOT
2055                          * lvalue argument of the underlying object.
2056                          *
2057                          * A method call via a reference object is a very
2058                          * weird case.
2059                          *
2060                          * Since the method called through an object winds up
2061                          * being a method taylored for that object, and we
2062                          * are calling through a reference to an object,
2063                          * the actual method will be looked up at run time
2064                          * and will match the object.  Thus we can safely
2065                          * indirect through the reference object for this
2066                          * one case.  Since (*ref_obj) is not normally
2067                          * allowed this will be special-cased at
2068                          * compile/run-time.
2069                          *
2070                          * Note that this occurs before we evaluate the
2071                          * compound expression on the right hand side.  Also
2072                          * note that since the resolver can be called multiple
2073                          * times on a shared expression, we have to be
2074                          * careful to shift the arguments around only once.
2075                          */
2076                         if ((ltype->ty_SQFlags & SF_METHOD) && 
2077                             (exRhs->ex_Flags & EXF_CALL_CONV) == 0
2078                         ) {
2079                                 Exp *obj;
2080
2081                                 exRhs->ex_Flags |= EXF_CALL_CONV;
2082
2083                                 switch(exLhs->ex_Token) {
2084                                 case TOK_STRIND:        /* indirect */
2085                                         obj = exLhs->ex_Lhs;
2086                                         if (obj->ex_Type->ty_Op == TY_PTRTO) {
2087                                                 Exp *nexp = AllocExp(NULL);
2088
2089                                                 nexp->ex_Lhs = obj;
2090                                                 nexp->ex_Token = TOK_PTRIND;
2091                                                 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_PtrType.et_Type);
2092                                                 nexp->ex_Flags |= EXF_RESOLVED |
2093                                                                   EXF_UNARY;
2094                                                 LexDupRef(&obj->ex_LexRef,
2095                                                           &nexp->ex_LexRef);
2096                                                 exLhs->ex_Token = TOK_DOT;
2097                                                 obj = nexp;
2098                                         } else if (obj->ex_Type->ty_Op ==
2099                                                    TY_CPTRTO) {
2100                                                 Exp *nexp = AllocExp(NULL);
2101
2102                                                 nexp->ex_Lhs = obj;
2103                                                 nexp->ex_Token = TOK_PTRIND;
2104                                                 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_CPtrType.et_Type);
2105                                                 nexp->ex_Flags |= EXF_RESOLVED |
2106                                                                   EXF_UNARY;
2107                                                 LexDupRef(&obj->ex_LexRef,
2108                                                           &nexp->ex_LexRef);
2109                                                 exLhs->ex_Token = TOK_DOT;
2110                                                 obj = nexp;
2111                                         } else if (obj->ex_Type->ty_Op ==
2112                                                     TY_REFTO) {
2113                                                 Exp *nexp = AllocExp(NULL);
2114
2115                                                 nexp->ex_Lhs = obj;
2116                                                 nexp->ex_Token = TOK_PTRIND;
2117                                                 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_RefType.et_Type);
2118                                                 nexp->ex_Flags |= EXF_RESOLVED |
2119                                                                   EXF_UNARY |
2120                                                                   EXF_INDREF;
2121                                                 LexDupRef(&obj->ex_LexRef,
2122                                                           &nexp->ex_LexRef);
2123                                                 obj = nexp;
2124                                         } else {
2125                                                 dassert_exp(obj, 0);
2126                                         }
2127                                         break;
2128                                 case TOK_DOT:   /* pass directly as lvalue */
2129                                         obj = exLhs->ex_Lhs;
2130                                         break;
2131                                 default:
2132                                         dassert_exp(exp, 0);
2133                                         obj = NULL;
2134                                         break;
2135                                 }
2136
2137                                 /*
2138                                  * Leave the lhs intact, but set the
2139                                  * duplication flag in case things get
2140                                  * nasty later.
2141                                  */
2142                                 exLhs->ex_Lhs = SetDupExp(sg, exLhs->ex_Lhs);
2143                                 obj->ex_Next = exRhs->ex_Lhs;
2144                                 exRhs->ex_Lhs = obj;
2145                         }
2146
2147                         /*
2148                          * Resolve the right hand side, which are the
2149                          * procedure arguments as a compound type.  This
2150                          * can get tricky.  XXX
2151                          *
2152                          * NOTE: We inherit the SF_LVALUE flag from the
2153                          *       return type.  Parent might turn it off.
2154                          */
2155                         /*d = exLhs->ex_Decl;*/
2156                         exRhs = resolveExp(isg, sg, exRhs,
2157                                            ltype->ty_ProcType.et_ArgsType, 1);
2158                         exType = ltype->ty_ProcType.et_RetType;
2159                 }
2160                 break;
2161         case TOK_COMPOUND:
2162                 /*
2163                  * (NOTE EARLY RETURN)
2164                  *
2165                  * A compound expression should always be an RVALUE, but
2166                  * might contain LVALUEs (XXX).
2167                  */
2168                 exp = resolveCompoundExp(isg, sg, exp, itype);
2169                 return(exp);
2170                 /* not reached */
2171         case TOK_TYPEOF:
2172                 /*
2173                  * The caller must be able to handle a type return when
2174                  * typeof() is used.
2175                  */
2176                 dassert_exp(exp, exFlags & EXF_REQ_TYPE);
2177                 /* fall through */
2178         case TOK_SIZEOF:
2179         case TOK_ARYSIZE:
2180                 /*
2181                  * If an expression was supplied, convert it to a type.
2182                  *
2183                  * NOTE: ex_Flags hints must 'always happen' since we may be
2184                  *       modifying an expression that will later be Dup'd.
2185                  */
2186                 if ((exFlags & EXF_RET_TYPE) == 0) {
2187                         dassert(exLhs != NULL);
2188                         exLhs->ex_Flags |= EXF_REQ_TYPE;
2189                         exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2190                         exType = exLhs->ex_Type;
2191                         exFlags &= ~EXF_UNARY;
2192                         exFlags |= EXF_RET_TYPE;
2193                         /* XXX delete the lhs */
2194                 } else {
2195                         exType = resolveType(exType);
2196                 }
2197                 switch(exToken) {
2198                 case TOK_SIZEOF:
2199                         exId = StrTableInt(exType->ty_Bytes);
2200                         exp->ex_Token = exToken = TOK_INTEGER;
2201                         exType = &SizeType;
2202                         exFlags &= ~EXF_RET_TYPE;
2203                         break;
2204                 case TOK_ARYSIZE:
2205                         dassert_exp(exp, exType->ty_Op == TY_ARYOF);
2206                         if (exType->ty_AryType.et_Type->ty_Bytes) {
2207                                 exId = StrTableInt(exType->ty_Bytes /
2208                                         exType->ty_AryType.et_Type->ty_Bytes);
2209                         } else {
2210                                 exId = StrTableInt(0);
2211                         }
2212                         exp->ex_Token = exToken = TOK_INTEGER;
2213                         exType = &SizeType;
2214                         exFlags &= ~EXF_RET_TYPE;
2215                         break;
2216                 case TOK_TYPEOF:
2217                         /* type is returned */
2218                         break;
2219                 }
2220                 break;
2221         default:
2222                 dassert_exp(exp, 0);
2223                 break;
2224         }
2225
2226         /*
2227          * Resolve the type.
2228          */
2229         if (exType) {
2230                 exType = resolveType(exType);
2231                 /* XXX exType was ex_Type */
2232
2233                 /*
2234                  * If we can autocast and itype is compound and the
2235                  * expression turns out to not be compound, then the Rune
2236                  * language converts the expression to compound.  This way
2237                  * (int x, int y = 2) = ( 7 ); works because ( 7 ) is
2238                  * parsed as a standard expression and thus not compound.
2239                  *
2240                  * (another way to do it would be to require that the element
2241                  *  be named, i.e. (x:7), which is compound after standard
2242                  *  parsing).
2243                  */
2244                 if (autocast && itype && 
2245                     itype->ty_Op == TY_COMPOUND &&
2246                     exType->ty_Op != TY_COMPOUND) {
2247                         saveExpCopy(&copy, exp);
2248                         exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2249                         exp = resolveCompoundExp(isg, sg, exp, itype);
2250                         loadExpCopy(&copy, exp);
2251                 }
2252
2253                 /*
2254                  * If the type hint did not succeed we may have to cast the
2255                  * expression to the requested type.  Note that if the itype
2256                  * was set as part of an array optimization request which could
2257                  * not be handled, we must ignore itype.
2258                  *
2259                  * Note that SimilarType() will allow exp->ex_Type to be a
2260                  * var-args TY_ARGS, and since the original Rhs of a call
2261                  * is set to the procedure arguments type, VarType.et_Type
2262                  * should match exactly.
2263                  */
2264                 if (itype &&
2265                     (exFlags & (EXF_REQ_ARRAY|EXF_RET_ARRAY)) != EXF_REQ_ARRAY
2266                 ) {
2267                         if ((itype->ty_Flags & TF_RESOLVED) == 0)
2268                                 itype = resolveType(itype);
2269                         if ((itype->ty_SQFlags & SF_LVALUE) &&
2270                             (exType->ty_SQFlags & SF_LVALUE) == 0
2271                         ) {
2272                                 /* XXX */
2273                                 fprintf(stderr, "Exp must be an lvalue here\n");
2274                                 dassert_exp(exp, 0);
2275                         }
2276                         if (!SimilarType(itype, exType) && autocast) {
2277                                 if (exp->ex_Flags & EXF_DUPEXP) {
2278                                         Exp *nexp = AllocExp(NULL);
2279
2280                                         nexp->u = exp->u;
2281                                         LexDupRef(&exp->ex_LexRef,
2282                                                   &nexp->ex_LexRef);
2283                                         exp = nexp;
2284                                         exFlags &= ~EXF_DUPEXP;
2285                                         /*exp = DupExp(sg, exp);*/
2286                                 }
2287                                 exFlags |= EXF_RESOLVED;
2288                                 exp = dupExpCopy(&copy, exp);
2289                                 exp = resolveExpCast(isg, sg, exp, itype);
2290                                 loadExpCopy(&copy, exp);
2291                         }
2292                 }
2293         }
2294         exFlags |= EXF_RESOLVED;
2295         exp = dupExpCopy(&copy, exp);
2296         return(exp);
2297 }
2298
2299 Exp *
2300 resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp)
2301 {
2302         Declaration *d;
2303
2304         exp = resolveExp(isg, sg, exp, NULL, 0);
2305
2306         if (exp->ex_Token != TOK_ID)
2307                 goto done;
2308         d = exp->ex_Decl;
2309         if ((d->d_StorDecl.ed_Type->ty_SQFlags & SF_CONST) == 0)
2310                 goto done;
2311
2312         switch(d->d_Op) {
2313         case DOP_ARGS_STORAGE:
2314         case DOP_STACK_STORAGE:
2315         case DOP_GLOBAL_STORAGE:
2316         case DOP_GROUP_STORAGE:
2317                 exp = d->d_StorDecl.ed_AssExp;
2318                 break;
2319         default:
2320                 break;
2321         }
2322 done:
2323         if (exp->ex_Token != TOK_INTEGER) {
2324                 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2325                 dassert_exp(exp, 0);
2326         }
2327         return exp;
2328 }
2329
2330 /*
2331  * resolveCompoundExp() - resolve a compound expression (called from 
2332  *                        resolveExp() and resolveExpOper()).
2333  *
2334  * Resolve a compound expression.  Compound expressions require
2335  * a compound type to normalize against.  This will work for
2336  * direct assignments, return values, casts, and procedure arguments
2337  * only. 
2338  *
2339  * NOTE: We can't use itype if EXF_REQ_ARRAY is specified because
2340  *       its hinting for the array optimization case, which we cannot do.
2341  *
2342  * Compound expressions may be used in conjuction with types 
2343  * reprsenting classes, compound types, and procedure arguments.  The
2344  * compound expression may contain subclasses of the superclasses expected
2345  * by itype.  This is only allowed if the procedure's body has not yet been
2346  * generated (for example, a method call in a subclass).
2347  *
2348  * Partially resolved operators are typically converted into procedure calls
2349  * and method calls are also partially resolved, so some elements may already 
2350  * be resolved.
2351  *
2352  * XXX named initialization, missing elements (structural
2353  * initialization), and so forth needs to be dealt with.
2354  */
2355 Exp *
2356 resolveCompoundExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype)
2357 {
2358         Exp **pscan;
2359         Exp *scan;
2360         Declaration *d;
2361         SemGroup *sg2;
2362         int varargs = 0;
2363         Type *type;
2364
2365         /*
2366          * Expression dup()ing
2367          */
2368         if (exp->ex_Flags & EXF_DUPEXP) {
2369 #if DUPEXP_DEBUG
2370                 static int count; fprintf(stderr, "DUPEXPC %d\n", ++count);
2371 #endif
2372                 exp = DupExp(sg, exp);
2373         }
2374
2375         if (itype && (exp->ex_Flags & EXF_REQ_ARRAY) == 0)
2376                 exp->ex_Type = itype;
2377
2378         /*
2379          * If we don't have a SemGroup to normalize against, XXX how should
2380          * we normalize the compound expression?
2381          */
2382         if (exp->ex_Type == NULL) {
2383                 dassert_exp(exp, 0);
2384         }
2385
2386         /*
2387          * Normalize the compound expression based on the
2388          * argument types expected by the procedure.  We have
2389          * to resolve the type before we start the scan in order
2390          * to ensure that d_Offset is properly assigned.
2391          *
2392          * Use the declarations found in the compound type 
2393          * semantic group to coerce the procedure arguments to
2394          * generate the correct compound type.  Note that resolveExp()
2395          * recursion must still use the SemGroup that was passed to us.
2396          *
2397          * XXX deal with defaults and pre-resolved arguments. XXX
2398          */
2399         type = exp->ex_Type = resolveType(exp->ex_Type);
2400
2401         switch(type->ty_Op) {
2402         case TY_ARGS:
2403                 sg2 = type->ty_ArgsType.et_SemGroup;
2404                 break;
2405         case TY_VAR:
2406                 sg2 = type->ty_VarType.et_SemGroup;
2407                 break;
2408         case TY_COMPOUND:
2409                 sg2 = type->ty_CompType.et_SemGroup;
2410                 break;
2411         case TY_CLASS:
2412                 sg2 = type->ty_ClassType.et_SemGroup;
2413                 break;
2414         default:
2415                 dassert_exp(exp, 0);
2416                 sg2 = NULL;     /* NOT REACHED */
2417                 break;
2418         }
2419         pscan = &exp->ex_Lhs;
2420
2421         /*
2422          * Scan the compound expression and match it up against the compound
2423          * type.
2424          */
2425         d = getHead(&sg2->sg_DeclList);
2426         while ((scan = *pscan) != NULL) {
2427                 if (scan->ex_ArgId != NULL) {
2428                         /*
2429                          * Named argument, find it
2430                          *
2431                          * (Overloading not allowed)
2432                          */
2433                         int eno = TOK_ERR_ID_NOT_FOUND;
2434                         d = FindDeclId(sg2, scan->ex_ArgId, &eno);
2435                         if (d == NULL) {
2436                                 ExpPrintError(scan, eno);
2437                                 dassert(0);
2438                         }
2439                 } else {
2440                         /*
2441                          * Unnamed argument, run through sequentially.  Skip
2442                          * any non-storage or global storage.
2443                          */
2444                         while (d && d->d_Op != DOP_ARGS_STORAGE &&
2445                                 d->d_Op != DOP_STACK_STORAGE &&
2446                                 d->d_Op != DOP_GROUP_STORAGE
2447                         ) {
2448                                 d = getSucc(&sg2->sg_DeclList, &d->d_Node);
2449                         }
2450
2451                         /*
2452                          * Ran out of storage declarations.  If this is a
2453                          * var-args SemGroup then we actually create a new
2454                          * SemGroup (and eventually a new type) to represent
2455                          * it.
2456                          *
2457                          * We then extend the varargs SemGroup.  This isn't
2458                          * pretty.
2459                          */
2460                         if (d == NULL) {
2461                                 if (varargs == 0 &&
2462                                     (sg2->sg_Flags & SGF_VARARGS)) {
2463                                         sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
2464 #if 0
2465                                         if (resolveSemGroup1(sg3))
2466                                                 resolveSemGroup2(sg3);
2467                                         sg2 = sg3;
2468 #endif
2469                                         varargs = 1;
2470                                 }
2471                                 if (varargs == 0) {
2472                                         fprintf(stderr,
2473                                                 "Too many arguments in "
2474                                                 "expression\n");
2475                                         dassert_exp(scan, 0);
2476                                 }
2477                         }
2478                 }
2479
2480                 /*
2481                  * Unlink the expression from the compound list temporarily
2482                  * so we can safely resolve it.  Either cast the expression
2483                  * to the compound element, or create a compound element
2484                  * (e.g. varargs call) to match the expression.
2485                  *
2486                  * Due to the resolver moving things around, the elements of
2487                  * a compound expression are sometimes resolved multiple times.
2488                  */
2489                 *pscan = scan->ex_Next;
2490                 scan->ex_Next = NULL;
2491                 if (d) {
2492                         Type *stype = d->d_StorDecl.ed_Type;
2493                         int autocast;
2494
2495                         /*
2496                          * HACK! XXX YYY
2497                          */
2498                         if (SimilarType(stype, &PointerType) &&
2499                             (stype->ty_SQFlags & SF_LVALUE) == SF_LVALUE
2500                         ) {
2501                                 stype = NULL;
2502                                 autocast = 0;
2503                         } else {
2504                                 autocast = 1;
2505                         }
2506                         if ((scan->ex_Flags & EXF_RESOLVED) == 0) {
2507                                 scan = resolveExp(isg, sg, scan,
2508                                                   stype, autocast);
2509                         } else if (stype) {
2510                                 /*
2511                                  * Since we have already resolved the
2512                                  * expression we need to do the same sanity
2513                                  * checking that it would do to cast.
2514                                  */
2515                                 dassert_exp(scan,
2516                                     (stype->ty_SQFlags & SF_LVALUE) == 0 ||
2517                                     (scan->ex_Type->ty_SQFlags & SF_LVALUE));
2518                                 if (!SimilarType(stype, scan->ex_Type)) {
2519                                         scan = resolveExpCast(isg, sg, scan,
2520                                                               stype);
2521                                 }
2522                         }
2523                 } else {
2524                         Scope tscope = INIT_SCOPE(0);
2525
2526                         if ((scan->ex_Flags & EXF_RESOLVED) == 0)
2527                                 scan = resolveExp(isg, sg, scan, NULL, 0);
2528                         dassert(varargs != 0);
2529                         d = AllocDeclaration(sg2, DOP_ARGS_STORAGE, &tscope);
2530                         d->d_StorDecl.ed_Type = DEL_LVALUE(scan->ex_Type);
2531                         ++sg2->sg_VarCount;
2532                         d->d_Bytes = scan->ex_Type->ty_Bytes;
2533                         d->d_AlignMask = scan->ex_Type->ty_AlignMask;
2534
2535                         /*
2536                          * __align(%d) scope qualifier, override the type's
2537                          * alignment
2538                          */
2539                         if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
2540                             d->d_Scope.s_AlignOverride) {
2541                                 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
2542                         }
2543
2544 #if 0
2545                         sg2->sg_Bytes = (sg2->sg_Bytes + d->d_AlignMask) &
2546                                         ~d->d_AlignMask;
2547 #endif
2548                         d->d_Offset = sg2->sg_Bytes;
2549 #if 0
2550                         sg2->sg_Bytes += d->d_Bytes;
2551                         if (sg2->sg_AlignMask < d->d_AlignMask)
2552                                 sg2->sg_AlignMask = d->d_AlignMask;
2553 #endif
2554                 }
2555                 scan->ex_Next = *pscan;
2556                 *pscan = scan;
2557
2558                 /*
2559                  * If the declaration requires an LVALUE, assert that
2560                  * we have an lvalue.  Otherwise set the direct-store
2561                  * request (also see InterpCompoundExp).
2562                  */
2563                 if (d->d_ScopeFlags & SCOPE_LVALUE) {
2564                         if ((scan->ex_Type->ty_SQFlags & SF_LVALUE) == 0)
2565                                 fprintf(stderr, "argument must be an lvalue\n");
2566                         dassert_exp(scan,
2567                                     scan->ex_Type->ty_SQFlags & SF_LVALUE);
2568                 }
2569
2570                 /*
2571                  * accounting
2572                  */
2573                 d = getSucc(&sg2->sg_DeclList, &d->d_Node);
2574                 pscan = &scan->ex_Next;
2575         }
2576
2577         /*
2578          * Resolve the varargs sg2 after building it.
2579          */
2580         if (varargs) {
2581                 if (resolveSemGroup1(sg2))
2582                         resolveSemGroup2(sg2);
2583                 resolveStorageSemGroup(sg2, 0, 0);
2584         }
2585
2586         /*
2587          * If we made a var-args call, adjust the expression's type
2588          */
2589         if (varargs) {
2590                 dassert(type->ty_Op == TY_ARGS);
2591                 exp->ex_Type = resolveType(TypeToVarType(type, sg2));
2592         }
2593         exp->ex_Flags |= EXF_RESOLVED;
2594         return(exp);
2595 }
2596
2597 /*
2598  * resolveExpCast() - Cast the expression to the specified type and return
2599  *                    the cast expression.
2600  *
2601  *      Note that expression nodes depend on their ex_Type being correct,
2602  *      and also expressions may be shared, so be careful not to modify the
2603  *      ex_Type (or anything else) in the existing expression.
2604  *
2605  *      This code is somewhat different then resolveExpOper() and friends.
2606  *      The Exp argument has already been resolved so do not resolve it
2607  *      again, and the cast type already has SF_LVALUE set or cleared as
2608  *      appropriate (had better be cleared!)
2609  *
2610  *      As with operators we have to locate the cast declaration matching
2611  *      the cast we want to do.
2612  */
2613 static Exp *
2614 resolveExpCast(SemGroup *isg, SemGroup *sg, Exp *exp, Type *ltype)
2615 {
2616         Type *rtype;
2617         Declaration *d;
2618
2619         rtype = exp->ex_Type;
2620         dassert(rtype && ltype);
2621         /*
2622          * XXX attempt to cast from subclass to superclass?
2623          */
2624
2625         /*
2626          * XXX look in our local semantic hierarchy for a compatible cast ?
2627          */
2628
2629         /*
2630          * Look in the right hand (source) type for the cast
2631          */
2632         d = findCast(rtype, ltype, rtype);
2633
2634         /*
2635          * If that fails then look in the left hand (destination) type for
2636          * the cast.
2637          */
2638         if (d == NULL) {
2639                 d = findCast(ltype, ltype, rtype);
2640         }
2641 #if 1
2642         if (d == NULL && (rtype->ty_Op == TY_PTRTO ||
2643                           rtype->ty_Op == TY_REFTO ||
2644                           rtype->ty_Op == TY_CPTRTO)) {
2645                 d = findCast(&PointerType, ltype, rtype);
2646         }
2647 #endif
2648
2649         if (d == NULL) {
2650                 /*
2651                  * We could not find a specific cast operator.  There are
2652                  * some inherent casts that we can do.  We run through these
2653                  * in attempt to come up with matching types.
2654                  */
2655                 if (ltype->ty_Op != rtype->ty_Op &&
2656                     (ltype->ty_Op == TY_PTRTO || ltype->ty_Op == TY_CPTRTO ||
2657                     ltype->ty_Op == TY_ARYOF) &&
2658                     (rtype->ty_Op == TY_PTRTO || rtype->ty_Op == TY_CPTRTO ||
2659                     rtype->ty_Op == TY_ARYOF)) {
2660                         /*
2661                          * Pointers, C pointers, or arrays can be cast to
2662                          * pointers, C pointers, or arrays of the same type.
2663                          *
2664                          * Cast the right hand type to an equivalent
2665                          * pointer/cpointer/array of the right hand type
2666                          * and re-resolve the cast.
2667                          */
2668                         exp = ExpToCastExp(exp,
2669                                 resolveType(ChangeType(rtype, ltype->ty_Op)));
2670                         return(resolveExpCast(isg, sg, exp, ltype));
2671                 } else if (MatchType(ltype, rtype) <= SG_COMPAT_PART) {
2672                         /*
2673                          * If the types are compatible (casting rtype->ltype),
2674                          * we can cast trivially.
2675                          */
2676                         exp = ExpToCastExp(exp, ltype);
2677                 } else if (MatchType(&NumericType, ltype) <= SG_COMPAT_PART &&
2678                            MatchType(&NumericType, rtype) <= SG_COMPAT_PART) {
2679                         /*
2680                          * Casting from one numeric type to another must be
2681                          * supported by the interpreter/compiler.
2682                          */
2683                         exp = ExpToCastExp(exp, ltype);
2684                 } else if (SimilarType(&VoidType, ltype)) {
2685                         /*
2686                          * Casting anything to void is allowed (throwing the
2687                          * object away).  E.g. statement-expressions.
2688                          */
2689                         exp = ExpToCastExp(exp, ltype);
2690                 } else if (SimilarType(&VoidPtrType, ltype)) {
2691                         /*
2692                          * Casting a pointer to a (void *) is trivial, but is
2693                          * only allowed if the underlying structure does not
2694                          * contain any pointers.
2695                          *
2696                          * NOTE: Generally only used when a pointer is being
2697                          *       cast to an integer.  Rune does not allow
2698                          *       casting back to other pointer types.
2699                          *
2700                          * XXX validate integral # of objects fit in pointer
2701                          * range.
2702                          */
2703                         dassert_exp(exp, (rtype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2704                         exp = ExpToCastExp(exp, ltype);
2705                 } else if (SimilarType(&VoidRefType, ltype)) {
2706                         /*
2707                          * Casting a pointer to a (void @) is trivial.
2708                          *
2709                          * NOTE: Generally only used when a pointer is being
2710                          *       cast to an integer.  Rune does not allow
2711                          *       casting back to other pointer types.
2712                          *
2713                          * XXX validate integral # of objects fit in pointer
2714                          * range.
2715                          */
2716                         dassert_exp(exp, (rtype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2717                         exp = ExpToCastExp(exp, ltype);
2718                 } else if (SimilarType(rtype, &VoidPtrType)) {
2719                         /*
2720                          * Casting from a void pointer may not be trivial
2721                          * but we leave it up to the interpreter/compiler.
2722                          *
2723                          * Only allow if the target does not contain any
2724                          * pointers or if the right-hand-side is NULL.
2725                          *
2726                          * XXX validate integral # of objects fit in pointer
2727                          * range.
2728                          */
2729                         switch(ltype->ty_Op) {
2730                         case TY_REFTO:
2731                                 if ((exp->ex_Flags & EXF_NULL) == 0)
2732                                 dassert_exp(exp, (ltype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2733                                 break;
2734                         case TY_PTRTO:
2735                                 if ((exp->ex_Flags & EXF_NULL) == 0)
2736                                 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2737                                 break;
2738                         case TY_CPTRTO:
2739                                 break;
2740                         default:
2741                                 break;
2742                         }
2743                         exp = ExpToCastExp(exp, ltype);
2744                 } else if (ltype->ty_Op == rtype->ty_Op &&
2745                            (ltype->ty_Op == TY_PTRTO ||
2746                             ltype->ty_Op == TY_CPTRTO ||
2747                             ltype->ty_Op == TY_ARYOF)) {
2748                         /*
2749                          * We allow casts of pointers to similar numeric
2750                          * types if they are the same size, though this is
2751                          * really rather a hack.  This is mainly to handle
2752                          * the signed<->unsigned cast case.  XXX
2753                          */
2754                         int ok = 0;
2755
2756                         switch(ltype->ty_Op) {
2757                         case TY_PTRTO:
2758                                 if (MatchType(&NumericType,
2759                                               ltype->ty_PtrType.et_Type) <=
2760                                      SG_COMPAT_SUBCLASS &&
2761                                     MatchType(&NumericType,
2762                                               rtype->ty_PtrType.et_Type) <=
2763                                      SG_COMPAT_SUBCLASS &&
2764                                     ltype->ty_Bytes == rtype->ty_Bytes
2765                                 ) {
2766                                         exp = ExpToCastExp(exp, ltype);
2767                                         ok = 1;
2768                                 }
2769                                 break;
2770                         case TY_CPTRTO:
2771                                 if (MatchType(&NumericType,
2772                                               ltype->ty_CPtrType.et_Type) <=
2773                                      SG_COMPAT_SUBCLASS &&
2774                                     MatchType(&NumericType,
2775                                               rtype->ty_CPtrType.et_Type) <=
2776                                      SG_COMPAT_SUBCLASS &&
2777                                     ltype->ty_Bytes == rtype->ty_Bytes
2778                                 ) {
2779                                         exp = ExpToCastExp(exp, ltype);
2780                                         ok = 1;
2781                                 }
2782                                 break;
2783                         case TY_ARYOF:
2784                                 if (MatchType(&NumericType,
2785                                               ltype->ty_AryType.et_Type) <=
2786                                      SG_COMPAT_SUBCLASS &&
2787                                     MatchType(&NumericType,
2788                                               rtype->ty_AryType.et_Type) <=
2789                                      SG_COMPAT_SUBCLASS &&
2790                                     ltype->ty_Bytes == rtype->ty_Bytes
2791                                 ) {
2792                                         exp = ExpToCastExp(exp, ltype);
2793                                         ok = 1;
2794                                 }
2795                                 break;
2796                         }
2797                         if (ok == 0) {
2798                                 fprintf(stderr,
2799                                         "Unable to resolve cast from pointers "
2800                                         "to dissimilar numeric types "
2801                                         "%s to %s\n",
2802                                         TypeToStr(rtype, NULL),
2803                                         TypeToStr(ltype, NULL));
2804                                 dassert_exp(exp, 0);
2805                         }
2806                 } else {
2807                         fprintf(stderr,
2808                                 "Unable to resolve cast from %s to %s\n",
2809                                 TypeToStr(rtype, NULL),
2810                                 TypeToStr(ltype, NULL));
2811                         dassert_exp(exp, 0);
2812                 }
2813         } else if (d->d_ScopeFlags & SCOPE_INTERNAL) {
2814                 /*
2815                  * We found a cast operator and it is an internal operator
2816                  */
2817                 exp = ExpToCastExp(exp, ltype);
2818                 exp->ex_Decl = d;
2819         } else {
2820                 /*
2821                  * We found a cast operator and it is a Rune cast procedure.  We
2822                  * must convert the cast to a procedure call.  If we want
2823                  * resolveCompoundExp() to be able to generate a compatible
2824                  * procedure (in a subclass) we have to tell it about the
2825                  * procedure.
2826                  */
2827                 Exp *sexp;
2828
2829                 sexp = ExpToCompoundExp(exp, TOK_COMPOUND);
2830                 if (d->d_ProcDecl.ed_ProcBody == NULL)
2831                         sexp->ex_Decl = d;
2832                 sexp = resolveCompoundExp(isg, sg, sexp,
2833                               d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType);
2834                 exp = AllocExp(NULL);
2835                 exp->ex_Lhs = AllocExp(NULL);
2836                 exp->ex_Lhs->ex_Token = TOK_DECL;
2837                 exp->ex_Lhs->ex_Id = d->d_Id;
2838                 exp->ex_Lhs->ex_Decl = d;
2839                 exp->ex_Lhs->ex_Type = d->d_ProcDecl.ed_Type;
2840                 exp->ex_Lhs->ex_Flags |= EXF_RESOLVED;
2841                 exp->ex_Rhs  = sexp;
2842                 exp->ex_Flags |= EXF_BINARY;
2843                 exp->ex_Token = TOK_CALL;
2844                 /* XXX use ltype or procedure's rettype? */
2845                 exp->ex_Type = ltype;
2846                 LexDupRef(&sexp->ex_LexRef, &exp->ex_LexRef);
2847                 LexDupRef(&sexp->ex_LexRef, &exp->ex_Lhs->ex_LexRef);
2848         }
2849         exp->ex_Flags |= EXF_RESOLVED;
2850         return(exp);
2851 }
2852
2853 static
2854 Declaration *
2855 findCast(Type *btype, Type *ltype, Type *rtype)
2856 {
2857         SemGroup *sg;
2858         Declaration *d;
2859
2860         /*
2861          * Locate the base type.  If the base type does not have a SemGroup
2862          * there are no casts.  (XXX put system operators here)
2863          */
2864         sg = BaseType(&btype);
2865
2866         if (sg == NULL)
2867                 return(NULL);
2868
2869         /*
2870          * Look for the cast in the SemGroup
2871          */
2872         for (d = getHead(&sg->sg_DeclList);
2873              d;
2874              d = getSucc(&sg->sg_DeclList, &d->d_Node)
2875         ) {
2876                 if (d->d_Op == DOP_PROC && (d->d_ScopeFlags & SCOPE_CAST)) {
2877                         if (MatchCastTypes(d, ltype, rtype))
2878                                 return(d);
2879                 }
2880         }
2881
2882         /*
2883          * Failed.  If the base type is a compound type, look for the
2884          * cast in the SemGroup for each element making up the compound
2885          * type.  e.g. so (mycustomtype, double) would find the cast
2886          * in mycustomtype.
2887          */
2888         if (btype->ty_Op == TY_COMPOUND) {
2889                 for (d = getHead(&sg->sg_DeclList);
2890                          d;
2891                          d = getSucc(&sg->sg_DeclList, &d->d_Node)
2892                 ) {
2893                         Declaration *d2;
2894                         if (d->d_Op & DOPF_STORAGE) {
2895                                 d2 = findCast(d->d_StorDecl.ed_Type,
2896                                               ltype, rtype);
2897                         } else if (d->d_Op == DOP_TYPEDEF) {
2898                                 d2 = findCast(d->d_TypedefDecl.ed_Type,
2899                                               ltype, rtype);
2900                         } else {
2901                                 d2 = NULL;
2902                         }
2903                         if (d2)
2904                                 return(d2);
2905                 }
2906         }
2907         return(NULL);
2908 }
2909
2910
2911 /*
2912  * resolveExpOper() - resolve an operator
2913  *
2914  *      This is complex enough that it is broken out into its own procedure.
2915  *      Normally we just look the operator up but we have to special case
2916  *      pointer arithmatic because we do will not know until now that we
2917  *      have to do it.
2918  *
2919  *      itype is a return-type hint only.  resolveExpOper() can ignore it
2920  *      if it wishes.  We currently use it to detect cast-to-void, such as
2921  *      when an expression like "++i" is used in a for() loop or as a
2922  *      standalone statement.  This allows us to optimize the case.
2923  */
2924 static Exp *
2925 resolveExpOper(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype)
2926 {
2927         Declaration *d;
2928         int isPointerOp = 0;
2929         Exp copy;
2930
2931         loadExpCopy(&copy, exp);
2932         dassert_exp(exp, exp->ex_Id != NULL);
2933         if (exFlags & EXF_BINARY) {
2934                 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2935                 exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
2936         } else if (exFlags & EXF_UNARY) {
2937                 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2938         } else {
2939                 dassert_exp(exp, 0);
2940         }
2941
2942         /*
2943          * If the lhs is a pointer look the operator up in the Pointer
2944          * class first.  Operators in the Pointer class are special-cased.
2945          * A second pointer argument or a pointer return value must match
2946          * the lhs pointer.
2947          *
2948          * If this fails, or if the ltype is not a pointer, then look
2949          * the operator up normally.
2950          */
2951         if (exLhs->ex_Type->ty_Op == TY_PTRTO ||
2952             exLhs->ex_Type->ty_Op == TY_REFTO ||
2953             exLhs->ex_Type->ty_Op == TY_CPTRTO
2954         ) {
2955                 Type *ltype;
2956                 Type *rtype;
2957
2958                 if (exFlags & EXF_BINARY) {
2959                         rtype = exRhs->ex_Type;
2960                         ltype = exLhs->ex_Type;
2961                 } else {
2962                         dassert(exFlags & EXF_UNARY);
2963                         rtype = NULL;
2964                         ltype = exLhs->ex_Type;
2965                 }
2966                 d = findOper(&PointerType, exp->ex_Id, ltype, rtype);
2967                 if (d)
2968                         isPointerOp = 1;
2969                 else
2970                         d = findExpOper(&copy);
2971         } else {
2972                 d = findExpOper(&copy);
2973         }
2974
2975         /*
2976          * Fall through to finish up resolving the operator.  We just set
2977          * ex_Decl for internal operators, and construct a call for
2978          * non-internal procedural operators.
2979          */
2980         if (d) {
2981                 Declaration *d2;
2982                 Type *type;
2983                 SemGroup *sg2;
2984                 int count = 0;
2985
2986                 dassert_exp(exp, d != NULL);
2987                 dassert_exp(exp, d->d_Op == DOP_PROC);
2988                 dassert_exp(exp, d->d_ProcDecl.ed_Type->ty_Op == TY_PROC);
2989                 type = d->d_ProcDecl.ed_Type;
2990                 exType = type->ty_ProcType.et_RetType;
2991
2992                 /*
2993                  * Special case for internal Pointer ops.  The return type is
2994                  * the left-hand type (we may still optimize it to void later).
2995                  */
2996                 if (isPointerOp &&
2997                     (d->d_ScopeFlags & SCOPE_INTERNAL) && 
2998                     SimilarType(&VoidRefType, exType)
2999                 ) {
3000                         if (exType->ty_SQFlags & SF_LVALUE)
3001                                 exType = ADD_LVALUE(exLhs->ex_Type);
3002                         else
3003                                 exType = DEL_LVALUE(exLhs->ex_Type);
3004                 }
3005
3006                 type = d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType;
3007                 dassert(type->ty_Op == TY_ARGS);
3008                 sg2 = type->ty_ArgsType.et_SemGroup;
3009
3010                 /*
3011                  * Assert that LVALUE requirements are met.  XXX MatchType()
3012                  * code should disallow the non-lvalue-cast-to-lvalue case
3013                  * so we don't have to do a check here.
3014                  */
3015                 for (
3016                         d2 = getHead(&sg2->sg_DeclList);
3017                         d2;
3018                         d2 = getSucc(&sg2->sg_DeclList, &d2->d_Node)
3019                 ) {
3020                         if ((d2->d_Op & DOPF_STORAGE) &&
3021                             d2->d_Op != DOP_GLOBAL_STORAGE) {
3022                                 if (count == 0) {
3023                                         if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3024                                             (exLhs->ex_Type->ty_SQFlags &
3025                                              SF_LVALUE) == 0
3026                                         ) {
3027                                                 fprintf(stderr,
3028                                                         "lhs of exp must be "
3029                                                         "lvalue\n");
3030                                                 dassert_exp(exp, 0);
3031                                         }
3032                                 } else if (count == 1) {
3033                                         if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3034                                                 (exRhs->ex_Type->ty_SQFlags &
3035                                                  SF_LVALUE) == 0
3036                                         ) {
3037                                                 fprintf(stderr,
3038                                                         "rhs of exp must be "
3039                                                         "lvalue\n");
3040                                                 dassert_exp(exp, 0);
3041                                         }
3042                                 }
3043                                 ++count;
3044                         }
3045                 }
3046
3047                 if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3048                         /*
3049                          * Internal operator.  Optimize any cast to void
3050                          * by having the internal function deal with it.
3051                          * (since we aren't setting exType the optimization
3052                          * currently doesn't do anything, see ST_Exp)
3053                          */
3054                         exDecl = d;
3055                         if (itype == &VoidType) {
3056                                 /*exType = itype;*/
3057                                 exFlags |= EXF_RET_VOID;
3058                         }
3059                 } else {
3060                         /*
3061                          * Normal procedural operator.  Convert the left and
3062                          * right hand sides to a compound expression and
3063                          * convert exp to a TOK_CALL.  NOTE! ex_Rhs may be
3064                          * NULL (unary op).
3065                          *
3066                          * The compound expression may need to rewrite a
3067                          * subclass procedure, which it can do if the
3068                          * procedure's body has not yet been created (or
3069                          * duplicated from the superclass).  ex_Decl must
3070                          * be set in this case.
3071                          *
3072                          * Note that the expression structure may be shared.
3073                          * The conversion is permanent so that is ok.
3074                          *
3075                          * XXX keep the type intact?
3076                          */
3077                         exLhs->ex_Next = exRhs;
3078                         exRhs = exLhs;
3079                         exRhs = ExpToCompoundExp(exRhs, TOK_COMPOUND);
3080                         if (d->d_ProcDecl.ed_ProcBody == NULL)
3081                                 exRhs->ex_Decl = d;
3082                         exRhs = resolveCompoundExp(isg, sg, exRhs, type);
3083                         exLhs = AllocExp(NULL);
3084                         LexDupRef(&exp->ex_LexRef, &exLhs->ex_LexRef);
3085                         exLhs->ex_Token = TOK_ID;
3086                         exLhs->ex_Id = d->d_Id;
3087                         exLhs->ex_Decl = d;
3088                         exLhs->ex_Type = d->d_ProcDecl.ed_Type;
3089                         exLhs->ex_Flags |= EXF_RESOLVED;
3090                         exToken = exp->ex_Token = TOK_CALL;
3091                         exFlags = EXF_BINARY;
3092                 }
3093         }
3094         if (d == NULL) {
3095                 fprintf(stderr,
3096                         "Unable to resolve operator: %s\n", exp->ex_Id);
3097                 dassert_exp(exp, 0);
3098         }
3099         exFlags |= EXF_RESOLVED;
3100         return(dupExpCopy(&copy, exp));
3101 }
3102
3103 static void
3104 loadExpCopy(Exp *copy, Exp *exp)
3105 {
3106         copy->ex_Lhs = exp->ex_Lhs;
3107         copy->ex_Rhs = exp->ex_Rhs;
3108         copy->ex_Flags = exp->ex_Flags;
3109         copy->ex_Type = exp->ex_Type;
3110         copy->ex_Decl = exp->ex_Decl;
3111         copy->ex_Token = exp->ex_Token;
3112         copy->ex_Visibility = exp->ex_Visibility;
3113         copy->ex_Id = exp->ex_Id;
3114         copy->ex_ArgId = exp->ex_ArgId;
3115         copy->ex_AuxExp = exp->ex_AuxExp;
3116 }
3117
3118 static void
3119 saveExpCopy(Exp *copy, Exp *exp)
3120 {
3121         exp->ex_Lhs = copy->ex_Lhs;
3122         exp->ex_Rhs = copy->ex_Rhs;
3123         exp->ex_Flags = copy->ex_Flags;
3124         exp->ex_Type = copy->ex_Type;
3125         exp->ex_Decl = copy->ex_Decl;
3126         exp->ex_Token = copy->ex_Token;
3127         exp->ex_Visibility = copy->ex_Visibility;
3128         exp->ex_Id = copy->ex_Id;
3129         exp->ex_ArgId = copy->ex_ArgId;
3130         exp->ex_AuxExp = copy->ex_AuxExp;
3131 }
3132
3133 #define EXF_DUPSHAREFLAGS       -1
3134
3135 static Exp *
3136 dupExpCopy(Exp *copy, Exp *exp)
3137 {
3138         Exp *nexp;
3139
3140         if ((exp->ex_Flags & EXF_DUPEXP) == 0) {
3141                 saveExpCopy(copy, exp);
3142                 return(exp);
3143         }
3144
3145         /*
3146          * We can share the expression or subexpression across duplicated
3147          * elements in distinct subclasses if these conditions are met.
3148          *
3149          * Note: 0x80000000 for ex_Visibility simply means that the visibility
3150          * was never modified and can be changed for the first time.
3151          * Superclasses are resolved first so we should be ok.
3152          */
3153         if (exp->ex_Lhs == copy->ex_Lhs &&
3154                 exp->ex_Rhs == copy->ex_Rhs &&
3155                 ((exp->ex_Flags ^ copy->ex_Flags) & ~EXF_DUPSHAREFLAGS) == 0 &&
3156                 (exp->ex_Type == copy->ex_Type || exp->ex_Type == NULL) &&
3157                 exp->ex_Token == copy->ex_Token &&
3158                 (exp->ex_Decl == copy->ex_Decl || exp->ex_Decl == NULL) &&
3159                 (exp->ex_Id == copy->ex_Id || exp->ex_Id == NULL) &&
3160                 (exp->ex_ArgId == copy->ex_ArgId || exp->ex_ArgId == NULL) &&
3161                 (exp->ex_AuxExp == copy->ex_AuxExp || exp->ex_AuxExp == NULL) &&
3162                 (exp->ex_Visibility == copy->ex_Visibility ||
3163                  (exp->ex_Visibility & 0x80000000))
3164         ) {
3165 #if DUPEXP_DEBUG
3166                 static int count;
3167                 fprintf(stderr, "DUPEXPB COMPARE %d %p\n", ++count, exp);
3168 #endif
3169                 saveExpCopy(copy, exp);
3170                 return(exp);
3171         } 
3172
3173         nexp = AllocExp(NULL);
3174         LexDupRef(&exp->ex_LexRef, &nexp->ex_LexRef);
3175
3176 #if DUPEXP_DEBUG
3177         {
3178                 static int count;
3179                 fprintf(stderr,
3180                         "DUPEXPB %d %p lhs (%p,%p) rhs (%p,%p) "
3181                         "flags (%08x,%08x) types (%p, %p) "
3182                         "tokens (%04x, %04x), decl (%p, %p) "
3183                         "vis (%d, %d)\n",
3184                         ++count,
3185                         exp,
3186                         exp->ex_Lhs, copy->ex_Lhs,
3187                         exp->ex_Rhs, copy->ex_Rhs,
3188                         exp->ex_Flags & ~EXF_DUPSHAREFLAGS,
3189                         copy->ex_Flags & ~EXF_DUPSHAREFLAGS,
3190                         exp->ex_Type, copy->ex_Type,
3191                         exp->ex_Token, copy->ex_Token,
3192                         exp->ex_Decl, copy->ex_Decl,
3193                         exp->ex_Visibility, copy->ex_Visibility
3194                 );
3195                 ExpPrintError(exp, 0);
3196         }
3197 #endif
3198
3199         copy->ex_Flags &= ~EXF_DUPEXP;
3200         saveExpCopy(copy, nexp);
3201         nexp->u = exp->u;
3202         return(nexp);
3203 }
3204
3205 /*
3206  * resolveType() -      Resolve a type
3207  *
3208  *      This routine is responsible for resolving the size and alignment
3209  *      features of a type.  Note that we do not special-case LVALUE
3210  *      qualified types here.
3211  *
3212  *      This routine is also rsponsible for resolving the visibility of
3213  *      a type's elements.  Visibility is inherited from sub-types.  Base
3214  *      classes's visibility should already be set by resolveSuperClass()
3215  */
3216 Type *
3217 resolveType(Type *type)
3218 {
3219         SemGroup *sg = NULL;
3220         Type *otype = type;
3221         int do2 = 0;
3222
3223         if (type->ty_Flags & TF_RESOLVED)
3224                 return(type);
3225
3226         dassert_type(type, (type->ty_Flags & TF_RESOLVING) == 0);
3227         type->ty_Flags |= TF_RESOLVING;
3228
3229         switch(type->ty_Op) {
3230         case TY_CLASS:
3231                 /*
3232                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3233                  */
3234                 sg = type->ty_ClassType.et_SemGroup;
3235                 do2 = resolveSemGroup1(sg);
3236                 type->ty_Bytes = sg->sg_Bytes;
3237                 type->ty_AlignMask = sg->sg_AlignMask;
3238                 /* visibility already determined by resolveSuperClass? */
3239
3240                 /*
3241                  * Type inherits ISUNSIGNED from class.  This is a special
3242                  * flag helper for the interpreter and code generator.
3243                  */
3244                 if (sg->sg_Flags & SGF_ISUNSIGNED)
3245                         type->ty_Flags |= TF_ISUNSIGNED;
3246                 if (sg->sg_Flags & SGF_ISFLOATING)
3247                         type->ty_Flags |= TF_ISFLOATING;
3248                 dassert(type->ty_Visibility != 0);
3249                 break;
3250         case TY_CPTRTO:
3251                 /*
3252                  * NOTE: Do not set TF_HASLVPTR, C pointers are not tracked.
3253                  */
3254                 type->ty_Bytes = sizeof(void *);
3255                 type->ty_AlignMask = POINTER_ALIGN;
3256                 type->ty_CPtrType.et_Type =
3257                         resolveType(type->ty_CPtrType.et_Type);
3258                 type->ty_Visibility = type->ty_CPtrType.et_Type->ty_Visibility;
3259                 break;
3260         case TY_PTRTO:
3261                 /*
3262                  * Set TF_HASLVPTR, pointers are tracked.
3263                  */
3264                 type->ty_Bytes = sizeof(PointerStor);
3265                 type->ty_AlignMask = POINTER_ALIGN;
3266                 type->ty_PtrType.et_Type =
3267                         resolveType(type->ty_PtrType.et_Type);
3268                 type->ty_Visibility = type->ty_PtrType.et_Type->ty_Visibility;
3269                 type->ty_Flags |= TF_HASLVPTR;
3270                 break;
3271         case TY_REFTO:
3272                 /*
3273                  * Set TF_HASLVPTR, references are tracked.
3274                  */
3275                 type->ty_Bytes = sizeof(PointerStor);
3276                 type->ty_AlignMask = POINTER_ALIGN;
3277                 type->ty_RefType.et_Type =
3278                         resolveType(type->ty_RefType.et_Type);
3279                 type->ty_Visibility = type->ty_RefType.et_Type->ty_Visibility;
3280                 type->ty_Flags |= TF_HASLVPTR;
3281                 break;
3282         case TY_ARYOF:
3283                 /*
3284                  * Inherit TF_HASLVPTR (if array type is or contains something
3285                  * which needs to be tracked).
3286                  *
3287                  * XXX allow ArySize resolve to local expression?
3288                  * XXX use interpreter to resolve constant expression?
3289                  * XXX SemGroup passed as NULL.
3290                  *
3291                  * XXX hack, ex_ArySize can be shared amoungst qualified
3292                  *     array types.  Only resolve it once.  XXX
3293                  *
3294                  * YYY hack what is our ImportSemGroup ???
3295                  */
3296                 {
3297                         Exp *exp = type->ty_AryType.et_ArySize;
3298                         if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
3299                                 exp = resolveConstExp(NULL,
3300                                                  type->ty_AryType.et_SemGroup,
3301                                                  exp);
3302                         }
3303                         type->ty_AryType.et_ArySize = exp;
3304                         type->ty_AryType.et_Type =
3305                                 resolveType(type->ty_AryType.et_Type);
3306                         dassert(exp->ex_Token == TOK_INTEGER);
3307                         type->ty_AryType.et_Count = strtoq(exp->ex_Id, NULL, 0);
3308                         type->ty_AlignMask =
3309                                 type->ty_AryType.et_Type->ty_AlignMask;
3310                         type->ty_Bytes =
3311                                 type->ty_AryType.et_Type->ty_Bytes *
3312                                 type->ty_AryType.et_Count;
3313                 }
3314                 type->ty_Visibility = type->ty_AryType.et_Type->ty_Visibility;
3315                 type->ty_Flags |= type->ty_AryType.et_Type->ty_Flags &
3316                                   (TF_HASLVPTR | TF_HASCONSTRUCT |
3317                                    TF_HASDESTRUCT | TF_HASGCONSTRUCT |
3318                                    TF_HASGDESTRUCT);
3319                 break;
3320         case TY_COMPOUND:
3321                 /*
3322                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3323                  */
3324                 sg = type->ty_CompType.et_SemGroup;
3325                 do2 = resolveSemGroup1(sg);
3326                 type->ty_Bytes = sg->sg_Bytes;
3327                 type->ty_AlignMask = sg->sg_AlignMask;
3328                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3329                 break;
3330         case TY_VAR:
3331                 /*
3332                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3333                  */
3334                 sg = type->ty_VarType.et_SemGroup;
3335                 do2 = resolveSemGroup1(sg);
3336                 type->ty_Bytes = sg->sg_Bytes;
3337                 type->ty_AlignMask = sg->sg_AlignMask;
3338                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3339                 break;
3340         case TY_ARGS:
3341                 /*
3342                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3343                  */
3344                 sg = type->ty_ArgsType.et_SemGroup;
3345                 do2 = resolveSemGroup1(sg);
3346                 type->ty_Bytes = sg->sg_Bytes;
3347                 type->ty_AlignMask = sg->sg_AlignMask;
3348                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3349                 break;
3350         case TY_PROC:
3351                 /*
3352                  * NOTE: Storage not tracked.
3353                  */
3354                 type->ty_ProcType.et_ArgsType =
3355                         resolveType(type->ty_ProcType.et_ArgsType);
3356                 type->ty_ProcType.et_RetType =
3357                         resolveType(type->ty_ProcType.et_RetType);
3358                 type->ty_Bytes = 0;
3359                 type->ty_AlignMask = 0;
3360                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3361                 break;
3362         case TY_STORAGE:
3363                 /*
3364                  * NOTE: Base storage is not tracked.
3365                  */
3366                 type->ty_Bytes = type->ty_StorType.et_Bytes;
3367                 /* XXX check pwr of 2 */
3368                 if (type->ty_Bytes)
3369                         type->ty_AlignMask = type->ty_Bytes - 1;
3370                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3371                 break;
3372         case TY_UNRESOLVED:
3373                 /*
3374                  * NOTE: Tracking set by resolveType().
3375                  */
3376                 type->ty_Flags &= ~TF_RESOLVING;
3377                 type = resolveSuperClass(type);
3378                 if (type == NULL) {
3379                         errorDottedId(otype->ty_UnresType.et_DottedId,
3380                                       "Unable to resolve class");
3381                         dassert(0);
3382                 }
3383                 type = resolveType(type);
3384                 type->ty_Flags |= TF_RESOLVING;
3385                 /* visibility set by resolveSuperClass() */
3386                 break;
3387         case TY_DYNAMIC:
3388                 /*
3389                  * NOTE: Tracking unknown (must be handled at run-time).
3390                  */
3391                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3392                 break;
3393         case TY_IMPORT:
3394                 /*
3395                  * NOTE: Storage is persistent, so wrapper is not tracked.
3396                  */
3397                 type->ty_Visibility = SCOPE_ALL_VISIBLE;        /* XXX */
3398                 break;
3399         default:
3400                 dassert(0);
3401         }
3402         type->ty_Flags &= ~TF_RESOLVING;
3403         type->ty_Flags |= TF_RESOLVED;
3404         if (do2 && sg)
3405                 resolveSemGroup2(sg);
3406
3407         /*
3408          * Resolve tracking flags so the run-time can take appropriate
3409          * action.
3410          */
3411         if (sg) {
3412                 if (sg->sg_SRBase)
3413                         type->ty_Flags |= TF_HASLVPTR;
3414                 if (sg->sg_Flags & SGF_VARARGS)
3415                         type->ty_Flags |= TF_HASLVPTR;  /* XXX TF_VARARGS */
3416                 if (sg->sg_CBase)
3417                         type->ty_Flags |= TF_HASCONSTRUCT;
3418                 if (sg->sg_DBase)
3419                         type->ty_Flags |= TF_HASDESTRUCT;
3420                 /*
3421                  * Combine constructor/destructor hint flags for globals
3422                  * because we have just one linked list for global constructors
3423                  * and destructors (no need to optimize heavily).
3424                  */
3425                 if (sg->sg_GBase)
3426                         type->ty_Flags |= TF_HASGCONSTRUCT|TF_HASGDESTRUCT;
3427         }
3428
3429         /*
3430          * Resolve the default expression for the type, if any.
3431          *
3432          * XXX qualified types just copy the exp. bad bad YYY
3433          *
3434          * YYY resolveExp() no ISG (import sem group)
3435          */
3436         if (type->ty_AssExp) {
3437                 if ((type->ty_AssExp->ex_Flags & EXF_RESOLVED) == 0) {
3438                         type->ty_AssExp = resolveExp(NULL, sg, type->ty_AssExp,
3439                                                      DEL_LVALUE(type), 1);
3440                 }
3441         }
3442         return(type);
3443 }
3444
3445 /*
3446  * resolveSuperClass() - resolve an unresolved dotted id sequence into a class
3447  *
3448  *      Unresolved type identifier sequences must be resolved.  We are also
3449  *      responsible for setting the visibility of the type's elements.
3450  */
3451 Type *
3452 resolveSuperClass(Type *super)
3453 {
3454         string_t *dottedId;
3455         SemGroup *sg;
3456         Declaration *d;
3457         int visibility = SCOPE_ALL_VISIBLE;
3458         int eno = 0;
3459
3460         dassert_type(super, super->ty_Op == TY_UNRESOLVED);
3461
3462         dottedId = super->ty_UnresType.et_DottedId;
3463         sg = super->ty_UnresType.et_SemGroup;
3464
3465         d = FindDeclPath(NULL, super->ty_UnresType.et_ImportSemGroup,
3466                          sg, super,
3467                          dottedId, FDC_NULL, &visibility, -1, &eno);
3468         if (d == NULL) {
3469                 return(NULL);
3470         }
3471
3472         /*
3473          * Resolve the unresolved type.  Note that this occurs during class
3474          * resolution and we can't call resolveType() here without getting into
3475          * a loop, so we do not yet know storage requirements (ty_Bytes and
3476          * ty_Align).
3477          */
3478         switch(d->d_Op) {
3479         case DOP_CLASS:
3480                 super->ty_Op = TY_CLASS;
3481                 super->ty_ClassType.et_SemGroup = d->d_ClassDecl.ed_SemGroup;
3482                 super->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
3483                 super->ty_Visibility = visibility;
3484                 dassert(visibility);
3485                 /*
3486                  * XXX should we move the class from the unresolved list to
3487                  * the new SemGroup's actual list?
3488                  */
3489                 break;
3490         case DOP_TYPEDEF:
3491                 {
3492                         dassert_type(super, d->d_TypedefDecl.ed_Type != super);
3493                         TypeToQualType(
3494                                 d->d_TypedefDecl.ed_Type,
3495                                 super,
3496                                 super->ty_SQFlags |
3497                                  d->d_TypedefDecl.ed_Type->ty_SQFlags,
3498                                 super->ty_AssExp
3499                         );
3500                 }
3501                 super->ty_Visibility = visibility;
3502                 break;
3503         default:
3504                 errorDottedId(dottedId, "identifier is not a class or typedef");
3505                 dassert_type(super, 0);
3506         }
3507         return(super);
3508 }
3509
3510 /*
3511  * Resolve the declarations in a semantic group.  We have to do this if
3512  * (a) The declaration(s) would not otherwise be resolved by our statement
3513  * scan, or (b) We need definitive size/alignment information now rather
3514  * then later.
3515  *
3516  * SemGroup resolution occurs in two stages in order to deal with
3517  * resolver loops.  The first stage does just enough to figure out
3518  * how large the SemGroup is (e.g. doesn't run through pointers).
3519  * The second stage completes the process.
3520  *
3521  * NOTE!  This code does not resolve declarations related to executable
3522  * semantic groups, such as sub-blocks within a procedure, but it does
3523  * have to resolve procedure definitions found in Class's and such.
3524  *
3525  * NOTE!  This code handles the last stage of subclass refinement, by 
3526  * checking the validity of the refinement and setting sg_Compat properly.
3527  */
3528
3529 int
3530 resolveSemGroup1(SemGroup *sg)
3531 {
3532         Declaration *d;
3533
3534         if (sg->sg_Flags & SGF_RESOLVED)
3535                 return(0);
3536         if (sg->sg_Flags & SGF_RESOLVING) {
3537                 fprintf(stderr,
3538                         "Unable to resolve embedded recursive reference\n");
3539                 dassert_semgrp(sg, (sg->sg_Flags & SGF_RESOLVING) == 0);
3540         }
3541         sg->sg_Flags |= SGF_RESOLVING;
3542
3543         /*
3544          * First pass - resolve storage only.  Note that this specifically
3545          * does not try to handle the multiple semantic layers inside a
3546          * procedure.  See ResolveStorage() for that.
3547          */
3548         for (
3549                 d = getHead(&sg->sg_DeclList);
3550                 d;
3551                 d = getSucc(&sg->sg_DeclList, &d->d_Node)
3552         ) {
3553                 switch(d->d_Op) {
3554                 case DOP_CLASS:
3555                 case DOP_TYPEDEF:
3556                 case DOP_ALIAS:
3557                 case DOP_IMPORT:
3558                 case DOP_PROC:
3559                         break;
3560                 case DOP_STACK_STORAGE:
3561                         /*
3562                          * can't happen.  Stack storage is only used in
3563                          * executable contexts.
3564                          */
3565                         dassert_decl(d, 0);
3566                 case DOP_ARGS_STORAGE:
3567                 case DOP_GROUP_STORAGE:
3568                         switch(d->d_StorDecl.ed_Type->ty_Op) {
3569                         case TY_CPTRTO:
3570                                 d->d_Bytes = sizeof(void *);
3571                                 d->d_AlignMask = POINTER_ALIGN;
3572                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3573                                     d->d_Scope.s_AlignOverride) {
3574                                         d->d_AlignMask =
3575                                                 d->d_Scope.s_AlignOverride - 1;
3576                                 }
3577                                 break;
3578                         case TY_PTRTO:
3579                         case TY_REFTO:
3580                                 if (d->d_ScopeFlags & SCOPE_LVALUE) {
3581                                         /*
3582                                          * NOTE: d->d_Bytes is different from
3583                                          *       the size of the underlying
3584                                          *       type that the LValueStor
3585                                          *       points to.
3586                                          */
3587                                         dassert(d->d_Op == DOP_ARGS_STORAGE);
3588                                         d->d_Bytes = sizeof(LValueStor);
3589                                         d->d_AlignMask = LVALUE_ALIGN;
3590                                 } else {
3591                                         d->d_Bytes = sizeof(PointerStor);
3592                                         d->d_AlignMask = POINTER_ALIGN;
3593                                 }
3594                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3595                                     d->d_Scope.s_AlignOverride) {
3596                                         d->d_AlignMask =
3597                                                 d->d_Scope.s_AlignOverride - 1;
3598                                 }
3599                                 break;
3600                         default:
3601                                 resolveDecl(d);
3602                                 break;
3603                         }
3604                         if (sg->sg_AlignMask < d->d_AlignMask)
3605                                 sg->sg_AlignMask = d->d_AlignMask;
3606                         sg->sg_Bytes = (sg->sg_Bytes + d->d_AlignMask) &
3607                                        ~d->d_AlignMask;
3608                         d->d_Offset = sg->sg_Bytes;
3609                         sg->sg_Bytes += d->d_Bytes;
3610                         break;
3611                 case DOP_GLOBAL_STORAGE:
3612                         switch(d->d_StorDecl.ed_Type->ty_Op) {
3613                         case TY_CPTRTO:
3614                                 d->d_Bytes = sizeof(void *);
3615                                 d->d_AlignMask = POINTER_ALIGN;
3616                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3617                                     d->d_Scope.s_AlignOverride) {
3618                                         d->d_AlignMask =
3619                                                 d->d_Scope.s_AlignOverride - 1;
3620                                 }
3621                                 break;
3622                         case TY_PTRTO:
3623                         case TY_REFTO:
3624                                 d->d_Bytes = sizeof(PointerStor);
3625                                 d->d_AlignMask = POINTER_ALIGN;
3626                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3627                                     d->d_Scope.s_AlignOverride) {
3628                                         d->d_AlignMask =
3629                                                 d->d_Scope.s_AlignOverride - 1;
3630                                 }
3631                                 break;
3632                         default:
3633                                 resolveDecl(d);
3634                                 break;
3635                         }
3636                         if (sg->sg_GlobalAlignMask < d->d_AlignMask)
3637                                 sg->sg_GlobalAlignMask = d->d_AlignMask;
3638                         sg->sg_GlobalBytes = (sg->sg_GlobalBytes +
3639                                               d->d_AlignMask) & ~d->d_AlignMask;
3640                         d->d_Offset = sg->sg_GlobalBytes;
3641                         sg->sg_GlobalBytes += d->d_Bytes;
3642                         break;
3643                 default:
3644                         dassert_semgrp(sg, 0);
3645                         break;
3646                 }
3647         }
3648
3649         /*
3650          * Final alignment
3651          */
3652         sg->sg_Bytes = (sg->sg_Bytes + sg->sg_AlignMask) & ~sg->sg_AlignMask;
3653         sg->sg_GlobalBytes = (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
3654                              ~sg->sg_GlobalAlignMask;
3655         sg->sg_Flags |= SGF_RESOLVED;
3656         return(1);
3657 }
3658
3659 void
3660 resolveSemGroup2(SemGroup *sg)
3661 {
3662         Declaration *d;
3663
3664         /*
3665          * Second pass, resolve non-storage entities after setting
3666          * SGF_RESOLVED, these entities may legally embed this class (if
3667          * this is a class).
3668          *
3669          * Resolve pointers that were only partially resolved in the first
3670          * pass.
3671          *
3672          * Refinements have been resolved but we have to check them for
3673          * legality and set sg_Compat.
3674          *
3675          * Note that this is what allows us to typedef a subclass in its
3676          * superclass.  The typedef itself is safe.
3677          *
3678          * Also resolve storage pointer entities that were skipped in the
3679          * first pass.  Such pointers could point to ourselves.
3680          */
3681         for (
3682                 d = getHead(&sg->sg_DeclList);
3683                 d;
3684                 d = getSucc(&sg->sg_DeclList, &d->d_Node)
3685         ) {
3686                 if (d->d_ScopeFlags & SCOPE_REFINE) {
3687                         resolveDecl(d->d_Super);
3688                         resolveDecl(d);
3689                         RefineDeclaration(sg, d->d_Super, d);
3690                 }
3691                 switch(d->d_Op) {
3692                 case DOP_CLASS:
3693                 case DOP_TYPEDEF:
3694                 case DOP_ALIAS:
3695                 case DOP_IMPORT:
3696                 case DOP_PROC:
3697                         resolveDecl(d);
3698                         break;
3699                 case DOP_ARGS_STORAGE:
3700                 case DOP_GROUP_STORAGE:
3701                 /*case DOP_STACK_STORAGE:*/
3702                 case DOP_GLOBAL_STORAGE:
3703                         switch(d->d_StorDecl.ed_Type->ty_Op) {
3704                         case TY_CPTRTO:
3705                         case TY_PTRTO:
3706                         case TY_REFTO:
3707                                 resolveDecl(d);
3708                                 break;
3709                         }
3710                         break;
3711                 default:
3712                         dassert_semgrp(sg, 0);
3713                         break;
3714                 }
3715         }
3716         sg->sg_Flags &= ~SGF_RESOLVING;
3717 }
3718
3719 /*
3720  * findExpOper() -      Find operator declaration matching expression
3721  *
3722  *      Locate the operator declaration (a DOP_PROCDEF) that matches
3723  *      the expression or NULL if no match could be found.  The expression's
3724  *      left and right hand sides must already be resolved.
3725  *
3726  *      NOTE!  A temporary 'copy' Exp may be passed, not all fields are valid.
3727  */
3728 static
3729 Declaration *
3730 findExpOper(Exp *exp)
3731 {
3732         Type *ltype;
3733         Type *rtype;
3734         Declaration *d;
3735
3736         if (exp->ex_Flags & EXF_BINARY) {
3737                 rtype = exp->ex_Rhs->ex_Type;
3738                 ltype = exp->ex_Lhs->ex_Type;
3739         } else {
3740                 dassert(exp->ex_Flags & EXF_UNARY);
3741                 rtype = NULL;
3742                 ltype = exp->ex_Lhs->ex_Type;
3743         }
3744
3745         /*
3746          * XXX look in our local semantic hierarchy for a compatible operator ?
3747          */
3748
3749         /*
3750          * Attempt to find a matching operator from the left hand side
3751          */
3752         d = findOper(ltype, exp->ex_Id, ltype, rtype);
3753
3754         if (d || (exp->ex_Flags & EXF_BINARY) == 0)
3755                 return(d);
3756
3757         d = findOper(rtype, exp->ex_Id, ltype, rtype);
3758         return(d);
3759 }
3760
3761 static
3762 Declaration *
3763 findOper(Type *btype, string_t id, Type *ltype, Type *rtype)
3764 {
3765         SemGroup *sg;
3766         Declaration *d;
3767         int args = (rtype != NULL) ? 2 : 1;
3768
3769         /*
3770          * Locate the base type.  If the base type does not have a SemGroup
3771          * there are no operators.  (XXX put system operators here)
3772          */
3773         sg = BaseType(&btype);
3774
3775         if (sg == NULL)
3776                 return(NULL);
3777
3778         /*
3779          * Look for the operator in the SemGroup
3780          */
3781         for (d = FindOperId(sg, id, args); d; d = d->d_ONext) {
3782                 resolveDecl(d);
3783                 if (d->d_MyGroup == sg &&
3784                         d->d_Op == DOP_PROC &&
3785                         d->d_ProcDecl.ed_OperId == id &&
3786                         MatchOperatorTypes(d, ltype, rtype)
3787                 ) {
3788                         return(d);
3789                 }
3790         }
3791
3792         /*
3793          * Failed.  If the base type is a compound type, look for the
3794          * operator in the SemGroup for each element making up the compound
3795          * type.  e.g. so (mycustomtype, double) would find the operator
3796          * in mycustomtype.
3797          */
3798         if (btype->ty_Op == TY_COMPOUND) {
3799                 for (d = getHead(&sg->sg_DeclList);
3800                          d;
3801                          d = getSucc(&sg->sg_DeclList, &d->d_Node)
3802                 ) {
3803                         Declaration *d2;
3804                         if (d->d_Op & DOPF_STORAGE) {
3805                                 d2 = findOper(d->d_StorDecl.ed_Type, id,
3806                                               ltype, rtype);
3807                         } else if (d->d_Op == DOP_TYPEDEF) {
3808                                 d2 = findOper(d->d_TypedefDecl.ed_Type, id,
3809                                               ltype, rtype);
3810                         } else {
3811                                 d2 = NULL;
3812                         }
3813                         if (d2)
3814                                 return(d2);
3815                 }
3816         }
3817         return(NULL);
3818 }
3819
3820 static void
3821 errorDottedId(string_t *ary, const char *ctl, ...)
3822 {
3823         va_list va;
3824         int i;
3825
3826         va_start(va, ctl);
3827         vfprintf(stderr, ctl, va);
3828         va_end(va);
3829         fprintf(stderr, ": %s", ary[0]);
3830         for (i = 1; ary[i]; ++i)
3831                 fprintf(stderr, ".%s", ary[i]);
3832         fprintf(stderr, "\n");
3833 }
3834
3835 /*
3836  * ResolveStorage() -   Final storage resolution pass
3837  *
3838  *      This pass carefully scans the SemGroup hierarchy and assigns
3839  *      offsets to declarations.
3840  *
3841  *      PROCEDURES - all the various 'executable' semantic layers in
3842  *      a procedure are collapsed together for efficiency, so we only
3843  *      have to manage one context.  This means that the d_Offset 
3844  *      assigned to declarations in sub-blocks may exceed the sg_ size
3845  *      of the sub-block's SemGroup.  We do not attempt to resolve
3846  *      procedure body templates (d_ProcDecl.ed_OrigBody).
3847  *
3848  *      CLASSES - are given offsets in their SemGroup's relative to 0, if
3849  *                not already resolved.
3850  *
3851  *      IMPORTS - are given offsets in their SemGroup's relative to 0
3852  *
3853  *      COMPOUND TYPES - (such as procedure arguments) are given offsets
3854  *      in their SemGroup's relative to 0.
3855  *
3856  *      TEMPORARY STORAGE - expressions may require temporary storage
3857  *      for intermediate results.  That space is reserved here.
3858  *
3859  *      We specifically do not resolve unrelated storage.
3860  */
3861 void
3862 ResolveStorage(Stmt *st)
3863 {
3864         runesize_t noffset;
3865         runesize_t offset;
3866         runesize_t goffset;
3867         runesize_t ngoffset;
3868         SemGroup *sg = st->st_MyGroup;
3869
3870         /*
3871          * If this is an executable semantic layer or an import layer then
3872          * assign storage to declarations up-front.  Of the various
3873          * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
3874          * DOP_GLOBAL_STORAGE.
3875          *
3876          * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
3877          * sg will be NULL.
3878          */
3879         if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
3880                 Declaration *d;
3881
3882                 dassert((sg->sg_Flags & (SGF_RESOLVED|SGF_RESOLVING)) == 0);
3883
3884                 sg->sg_Flags |= SGF_RESOLVING;
3885
3886                 /*
3887                  * Procedures consolidate their storage.  To make d_Offset's
3888                  * come out properly.
3889                  */
3890                 if (st->st_Flags & STF_SEMTOP) {
3891                         dassert(sg->sg_Bytes == 0);
3892                         offset = 0;
3893                 } else {
3894                         offset = sg->sg_Parent->sg_Bytes;
3895                 }
3896
3897                 sg->sg_BlkOffset = offset;
3898
3899                 for (d = getHead(&sg->sg_DeclList);
3900                      d;
3901                      d = getSucc(&sg->sg_DeclList, &d->d_Node)
3902                 ) {
3903                         switch(d->d_Op) {
3904                         case DOP_STACK_STORAGE:
3905                         case DOP_ARGS_STORAGE:
3906                         case DOP_GROUP_STORAGE:
3907                                 offset = (offset + d->d_AlignMask) &
3908                                         ~d->d_AlignMask;
3909                                 dassert_decl(d, d->d_Offset == (runesize_t)-1);
3910                                 d->d_Offset = offset;
3911                                 offset += d->d_Bytes;
3912                                 break;
3913                         case DOP_GLOBAL_STORAGE:
3914                                 sg->sg_GlobalBytes =
3915                                         (sg->sg_GlobalBytes + d->d_AlignMask) &
3916                                         ~d->d_AlignMask;
3917                                 dassert_decl(d, d->d_Offset == (runesize_t)-1);
3918                                 d->d_Offset = sg->sg_GlobalBytes;
3919                                 sg->sg_GlobalBytes += d->d_Bytes;
3920                                 break;
3921                         default:
3922                                 break;
3923                         }
3924                 }
3925
3926                 /*
3927                  * Final alignment so, for example, arrays work properly.  We
3928                  * incorporate the storage into our parent at the end.
3929                  */
3930                 sg->sg_Bytes = (offset + sg->sg_AlignMask) &
3931                                ~sg->sg_AlignMask;
3932                 sg->sg_GlobalBytes =
3933                         (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
3934                         ~sg->sg_GlobalAlignMask;
3935                 sg->sg_BlkBytes = sg->sg_Bytes - sg->sg_BlkOffset;
3936                 sg->sg_Flags |= SGF_RESOLVED;
3937                 sg->sg_Flags &= ~SGF_RESOLVING;
3938         }
3939
3940         /*
3941          * Figure out how much temporary space we need to be able to execute
3942          * statements and expressions.  Temporary space, like the main
3943          * procedural space, must be inherited from and consolidated into
3944          * the top-level SemGroup
3945          */
3946         if (sg) {
3947                 offset = sg->sg_TmpBytes;
3948                 noffset = offset;
3949                 goffset = sg->sg_GlobalTmpBytes;
3950                 ngoffset = goffset;
3951         } else {
3952                 /*
3953                  * Root ST_Import.  avoid compiler warnings
3954                  */
3955                 offset = 0;
3956                 noffset = 0;
3957                 goffset = 0;
3958                 ngoffset = 0;
3959         }
3960
3961         switch(st->st_Op) {
3962         case ST_Import:
3963                 if (st->st_ImportStmt.es_DLL) {
3964                         void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
3965                                                    "resolveStorage");
3966                         if (func)
3967                                 func();
3968                 }
3969                 break;
3970         case ST_Module:
3971         case ST_Class:
3972                 break;
3973         case ST_Typedef:
3974                 {
3975                         resolveStorageDeclExp(st->st_TypedefStmt.es_Decl,
3976                                               &noffset, &ngoffset);
3977                 }
3978                 break;
3979         case ST_Decl:
3980                 /*
3981                  * Temporary space for declarations are handled here.
3982                  */
3983                 {
3984                         Declaration *d;
3985                         int i;
3986
3987                         d = st->st_DeclStmt.es_Decl;
3988                         for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
3989                                 runesize_t xoffset = offset;
3990                                 runesize_t xgoffset = goffset;
3991
3992                                 resolveStorageDeclExp(d, &xoffset, &xgoffset);
3993
3994                                 if (noffset < xoffset)
3995                                         noffset = xoffset;
3996                                 if (ngoffset < xgoffset)
3997                                         ngoffset = xgoffset;
3998                                 d = getSucc(&d->d_MyGroup->sg_DeclList,
3999                                             &d->d_Node);
4000                         }
4001                 }
4002                 break;
4003         case ST_Block:
4004                 break;
4005         case ST_Proc:
4006                 break;
4007         case ST_Nop:
4008                 break;
4009         case ST_Loop:
4010                 {
4011                         runesize_t xoffset;
4012
4013                         if (st->st_LoopStmt.es_BCond) {
4014                                 xoffset = offset;
4015                                 resolveStorageExp(st->st_LoopStmt.es_BCond,
4016                                                   &xoffset);
4017                                 if (noffset < xoffset)
4018                                         noffset = xoffset;
4019                         }
4020                         if (st->st_LoopStmt.es_ACond) {
4021                                 xoffset = offset;
4022                                 resolveStorageExp(st->st_LoopStmt.es_ACond,
4023                                                   &xoffset);
4024                                 if (noffset < xoffset)
4025                                         noffset = xoffset;
4026                         }
4027                         if (st->st_LoopStmt.es_AExp) {
4028                                 xoffset = offset;
4029                                 resolveStorageExp(st->st_LoopStmt.es_AExp,
4030                                                   &xoffset);
4031                                 if (noffset < xoffset)
4032                                         noffset = xoffset;
4033                         }
4034                 }
4035                 break;
4036         case ST_BreakCont:
4037                 break;
4038         case ST_Bad:
4039                 break;
4040         case ST_IfElse:
4041                 resolveStorageExp(st->st_IfStmt.es_Exp, &noffset);
4042                 break;
4043         case ST_Return:
4044                 if (st->st_RetStmt.es_Exp)
4045                         resolveStorageExp(st->st_RetStmt.es_Exp, &noffset);
4046                 break;
4047         case ST_Result:
4048                 if (st->st_ResStmt.es_Exp)
4049                         resolveStorageExp(st->st_ResStmt.es_Exp, &noffset);
4050                 break;
4051         case ST_Switch:
4052                 /*
4053                  * The switch expression's temporary data must be saved while
4054                  * we are executing the sub-statements (the cases).
4055                  */
4056                 resolveStorageExp(st->st_SwStmt.es_Exp, &noffset);
4057                 offset = noffset;
4058                 goffset = ngoffset;
4059                 break;
4060         case ST_Case:
4061                 if (st->st_CaseStmt.es_Exp)
4062                         resolveStorageExp(st->st_CaseStmt.es_Exp, &noffset);
4063                 break;
4064         case ST_Exp:
4065                 resolveStorageExp(st->st_ExpStmt.es_Exp, &noffset);
4066                 break;
4067         case ST_ThreadSched:
4068                 break;
4069         default:
4070                 dassert_stmt(st, 0);
4071         }
4072
4073         /*
4074          * Calculate storage requirements for substatements.  offset
4075          * acts as our base.  We union the storage for the substatements
4076          * together.  Note that often scan->sg_MyGroup == sg.
4077          */
4078         {
4079                 Stmt *scan;
4080
4081                 for (
4082                         scan = getHead(&st->st_List);
4083                         scan;
4084                         scan = getSucc(&st->st_List, &scan->st_Node)
4085                 ) {
4086                         if (scan->st_Op == ST_Class) {
4087                                 ResolveStorage(scan);
4088                         } else if (scan->st_Op == ST_Proc && 
4089                                    scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan
4090                         ) {
4091                                 /* Do not resolve template procedures! */
4092                         } else if (scan->st_Flags & STF_SEMTOP) {
4093                                 assert(scan->st_MyGroup != sg);
4094                                 ResolveStorage(scan);
4095                         } else {
4096                                 /*
4097                                  * This is a bit of a mess.  The baseline
4098                                  * sg_TmpBytes needs to be set so calculated
4099                                  * temporary offsets are relative to it, and
4100                                  * then restored.  Otherwise we might blow
4101                                  * away the SGF_TMPRESOLVED SemGroup
4102                                  *
4103                                  * XXX
4104                                  */
4105                                 runesize_t save_offset;
4106                                 runesize_t save_goffset;
4107                                 save_offset = scan->st_MyGroup->sg_TmpBytes;
4108                                 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
4109                                 scan->st_MyGroup->sg_TmpBytes = offset;
4110                                 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
4111                                 ResolveStorage(scan);
4112
4113                                 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
4114                                         scan->st_MyGroup->sg_TmpBytes = save_offset;
4115                                 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
4116                                         scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
4117                                 }
4118                                 if (noffset < scan->st_MyGroup->sg_TmpBytes)
4119                                         noffset = scan->st_MyGroup->sg_TmpBytes;
4120                                 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
4121                                         ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
4122                         }
4123                 }
4124         }
4125
4126         /*
4127          * If this is a new semantic level call resolveStorageSemGroup() to
4128          * do the final cleanup of SemGroup issues.  This will redundantly
4129          * calculate temporary space requirements.  Also, due to type/class
4130          * references the temporary space for a class may have already been
4131          * resolved.  Since a class can only contain declarations it had
4132          * better match what we calculate here.
4133          *
4134          * Note that for non-Class executable SemGroup's TmpBytes is
4135          * incorporated in a downward fashion while sg_Bytes is incorporated
4136          * in an upward fashion.  It can become quite confusing.  Don't ask
4137          * me why I did it that way.
4138          */
4139         if (st->st_Flags & STF_SEMANTIC) {
4140                 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
4141                         resolveStorageSemGroup(sg, noffset, ngoffset);
4142                 } else {
4143                         dassert(sg->sg_TmpBytes == noffset && 
4144                                 sg->sg_GlobalTmpBytes == ngoffset);
4145                 }
4146         } else if (sg) {
4147                 sg->sg_TmpBytes = noffset;
4148                 sg->sg_GlobalTmpBytes = ngoffset;
4149         } /* else this is the Root st_Import */
4150
4151         if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
4152                 sg->sg_Parent->sg_Bytes = sg->sg_Bytes;
4153                 if (sg->sg_Parent->sg_AlignMask < sg->sg_AlignMask)
4154                         sg->sg_Parent->sg_AlignMask = sg->sg_AlignMask;
4155         }
4156 }
4157
4158 /*
4159  * resolveStorageDeclExp() - resolve the storage reservation required to
4160  *                           process an expression.
4161  *
4162  *      This is an expression tree traversal storage resolution procedure.
4163  *      We have to traverse through declarations to get to default assignments
4164  *      and such.
4165  *
4166  *      If a declaration has no assign default the underlying type may itself
4167  *      have an assigned default which must be dealt with.
4168  */
4169 static void
4170 resolveStorageDeclExp(Declaration *d, runesize_t *offset, runesize_t *goffset)
4171 {
4172         switch(d->d_Op) {
4173         case DOP_CLASS:
4174                 /* recursion already dealt with */
4175                 break;
4176         case DOP_ARGS_STORAGE:
4177         case DOP_STACK_STORAGE:
4178         case DOP_GROUP_STORAGE:
4179                 {
4180                         Type *type = d->d_StorDecl.ed_Type;
4181
4182                         resolveStorageType(type);
4183                         if (d->d_StorDecl.ed_AssExp) {
4184                                 resolveStorageExp(d->d_StorDecl.ed_AssExp,
4185                                                   offset);
4186                         }
4187                 }
4188                 break;
4189         case DOP_GLOBAL_STORAGE:
4190                 {
4191                         Type *type = d->d_StorDecl.ed_Type;
4192
4193                         resolveStorageType(type);
4194                         if (d->d_StorDecl.ed_AssExp) {
4195                                 resolveStorageExp(d->d_StorDecl.ed_AssExp,
4196                                                   goffset);
4197                         }
4198                 }
4199                 break;
4200         case DOP_ALIAS:
4201                 /*
4202                  * Never try to resolve storage considerations for an
4203                  * alias's assignment in the declaration itself.  The
4204                  * run-time context depends on who and how many other
4205                  * parts of the program reference the alias and the expression
4206                  * tree will be duplicated for each.
4207                  */
4208 #if 0
4209                 if (d->d_ScopeFlags & SCOPE_GLOBAL)
4210                         resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL);
4211                 else
4212                         resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL);
4213 #endif
4214                 break;
4215         case DOP_TYPEDEF:
4216                 /* XXX what about ty_AssExp ? should be in global space */
4217                 break;
4218         case DOP_IMPORT:
4219                 /* recursion already dealt with */
4220                 break;
4221         case DOP_PROC:
4222                 break;
4223         default:
4224                 dassert_decl(d, 0);
4225         }
4226 }
4227
4228 /*
4229  * resolveStorageExp() - resolve the temporary storage required to
4230  *                       support the expression, if any.
4231  *
4232  * We do not need to assign storage for expressions which return
4233  * lvalues, because they will simply return a pointer into
4234  * non-temporary storage.
4235  */
4236 static runesize_t
4237 resolveStorageExpOnly(Exp *exp, runesize_t *offset)
4238 {
4239         Type *type;
4240
4241         /*
4242          * Stop if the expression resolves to a type rather then a value,
4243          * e.g. when you do something like switch (typeof(int)) { ... }
4244          */
4245         if (exp->ex_Flags & EXF_RET_TYPE)
4246                 return(*offset);
4247
4248         /*
4249          * Assign temporary offset.  This offset does not overlap temporary
4250          * space reserved for sub-expressions.
4251          *
4252          * We must have an assigned type.  Expression sequences like:
4253          * 'module.blah' are collapsed into 'blah' long before we get
4254          * here, or they should be.  We should not encounter any
4255          * TOK_TCMV_ID expression tokens.  Structural id's (the right hand
4256          * side of X.Y) are resolved by their parent expression node and
4257          * no typing or temporary space is required.
4258          *
4259          * Expressions that return lvalues do not need temporary space.
4260          */
4261         type = exp->ex_Type;
4262         if (type == NULL) {
4263                 switch(exp->ex_Token) {
4264                 case TOK_STRUCT_ID:
4265                 case TOK_SEMGRP_ID:
4266                         break;
4267                 default:
4268                         printf("EXP %p %04x %p\n",
4269                                exp, exp->ex_Token, exp->ex_Decl);
4270                         dassert_exp(exp, 0);
4271                         break;
4272                 }
4273         } else if (type->ty_SQFlags & SF_LVALUE) {
4274                 /*
4275                  * Expressive elements which return lvalues do not get
4276                  * temporary space.  Note that this also prevents lvalues
4277                  * such as large arrays (int ary[999999999]) from reserving
4278                  * unnecessary stack space.
4279                  *
4280                  * NOTE: SF_LVALUE is unrelated to SCOPE_LVALUE.  SCOPE_LVALUE
4281                  *       applies to SemGroup storage (LValueStor).  SF_LVALUE
4282                  *       merely flags the type for an expression as expecting
4283                  *       or not expecting an lvalue.
4284                  */
4285 #if 0
4286                 /*
4287                  * XXX removeme, LValueStor only applies to semgroups
4288                  */
4289                 runesize_t lvmask = sizeof(LValueStor) - 1;
4290                 *offset = (*offset + lvmask) & ~lvmask;
4291                 exp->ex_TmpOffset = *offset;
4292                 *offset = *offset + (lvmask + 1);
4293 #endif
4294                 exp->ex_TmpOffset = -1;
4295         } else {
4296                 /*
4297                  * Reserve temporary space for potential intermediate
4298                  * results.
4299                  */
4300                 *offset = (*offset + type->ty_AlignMask) & ~type->ty_AlignMask;
4301                 exp->ex_TmpOffset = *offset;
4302                 *offset = *offset + type->ty_Bytes;
4303         }
4304         return (*offset);
4305 }
4306
4307 static void
4308 resolveStorageExpSub(Exp *exp, runesize_t *offset)
4309 {
4310         /*
4311          * Early term
4312          */
4313         if (exp->ex_Flags & EXF_RET_TYPE)
4314                 return;
4315
4316         /*
4317          * Calculate the overlapping temporary space for sub-trees.
4318          */
4319         if (exp->ex_Flags & EXF_BINARY) {
4320                 /*
4321                  * Ensure lhs's temporary storage on-return does not intefere
4322                  * with rhs's or vise-versa.  To do this we need to calculate
4323                  * the initial storage for both sides first.
4324                  */
4325                 runesize_t xoffset;
4326                 runesize_t roffset;
4327                 roffset = *offset;
4328
4329                 xoffset = roffset;
4330                 resolveStorageExp(exp->ex_Lhs, &xoffset);
4331                 if (*offset < xoffset)
4332                         *offset = xoffset;
4333                 xoffset = roffset;
4334                 resolveStorageExp(exp->ex_Rhs, &xoffset);
4335                 if (*offset < xoffset)
4336                         *offset = xoffset;
4337         } else if (exp->ex_Flags & EXF_UNARY) {
4338                 resolveStorageExp(exp->ex_Lhs, offset);
4339                 dassert_exp(exp, exp->ex_Lhs->ex_Next == NULL);
4340         } else if (exp->ex_Flags & EXF_COMPOUND) {
4341                 /*
4342                  * each element will be copied into the compound storage
4343                  * in turn, so we can union the temporary storage required
4344                  * for each element.
4345                  */
4346                 Exp *scan;
4347                 runesize_t noffset = *offset;
4348
4349                 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
4350                         runesize_t xoffset = *offset;
4351
4352                         dassert_exp(scan, scan->ex_Type != NULL);
4353
4354                         resolveStorageExp(scan, &xoffset);
4355                         if (noffset < xoffset)
4356                                 noffset = xoffset;
4357                 }
4358                 *offset = noffset;
4359         }
4360
4361 #if 0
4362         /* XXX what about alias assign-expressions */
4363         else if (exp->ex_Flags & EXF_ALIAS) {
4364 #if 0
4365                 dassert_decl(exp->ex_Decl,
4366                              (exp->ex_Decl->d_ScopeFlags & SCOPE_GLOBAL) == 0);
4367 #endif
4368                 resolveStorageExp(exp->ex_Decl->d_AliasDecl.ed_AssExp, offset);
4369         }
4370 #endif
4371 }
4372
4373 static void
4374 resolveStorageExp(Exp *exp, runesize_t *offset)
4375 {
4376         runesize_t noffset;
4377         runesize_t xoffset;
4378
4379         xoffset = *offset;
4380         noffset = resolveStorageExpOnly(exp, &xoffset);
4381         xoffset = noffset;
4382         resolveStorageExpSub(exp, &xoffset);
4383         if (*offset < xoffset)
4384                 *offset = xoffset;
4385 }
4386
4387 /*
4388  * resolveStorageType() - temporary space required to initialize type defaults
4389  *
4390  *      Figure out the temporary space required to initialize a type's
4391  *      defaults.  Note that the space will be figured independantly
4392  *      for any SemGroup's.
4393  */
4394 static
4395 void
4396 resolveStorageType(Type *type)
4397 {
4398         switch(type->ty_Op) {
4399         case TY_CLASS:
4400                 resolveStorageSemGroup(type->ty_ClassType.et_SemGroup, 0, 0);
4401                 break;
4402         case TY_ARYOF:
4403                 resolveStorageType(type->ty_AryType.et_Type);
4404                 break;
4405         case TY_COMPOUND:
4406                 resolveStorageSemGroup(type->ty_CompType.et_SemGroup, 0, 0);
4407                 break;
4408         case TY_PROC:
4409                 resolveStorageType(type->ty_ProcType.et_ArgsType);
4410                 resolveStorageType(type->ty_ProcType.et_RetType);
4411                 break;
4412         case TY_IMPORT:
4413                 resolveStorageSemGroup(type->ty_ImportType.et_SemGroup, 0, 0);
4414                 break;
4415         case TY_ARGS:
4416                 resolveStorageSemGroup(type->ty_ArgsType.et_SemGroup, 0, 0);
4417                 break;
4418         case TY_VAR:
4419                 resolveStorageSemGroup(type->ty_VarType.et_SemGroup, 0, 0);
4420                 break;
4421         case TY_CPTRTO:
4422                 resolveStorageType(type->ty_CPtrType.et_Type);
4423                 break;
4424         case TY_PTRTO:
4425                 resolveStorageType(type->ty_PtrType.et_Type);
4426                 break;
4427         case TY_REFTO:
4428                 resolveStorageType(type->ty_RefType.et_Type);
4429                 break;
4430         case TY_STORAGE:
4431         case TY_DYNAMIC:
4432                 /* 
4433                  * nothing to be done here.
4434                  */
4435                 break;
4436         case TY_UNRESOLVED: /* should be no unresolved types at this stage */
4437         default:
4438                 dassert_type(type, 0);
4439         }
4440         if (type->ty_AssExp) {
4441                 if ((type->ty_Flags & TF_ASSEXPSTOR) == 0) {
4442                         type->ty_Flags |= TF_ASSEXPSTOR;
4443                         resolveStorageExp(type->ty_AssExp, &type->ty_TmpBytes);
4444                 }
4445         }
4446 }
4447
4448 /*
4449  * This is used to resolve temporary storage requirements for
4450  * SemGroup's related to classes and compound types.  Temporary storage
4451  * requirements are calculated on a SemGroup-by-SemGroup basis and not
4452  * aggregated into any parent.
4453  *
4454  * We also reverse the constructor and destructor lists (sg_CBase and
4455  * sg_DBase), and the pointer/lvalue list (SRBase).  These lists were
4456  * originally constructed by prepending and are thus in the wrong order.
4457  */
4458 static
4459 void
4460 resolveStorageSemGroup(SemGroup *sg, runesize_t noffset, runesize_t ngoffset)
4461 {
4462         Declaration *d;
4463         Declaration *d2;
4464
4465         if (sg->sg_Flags & SGF_TMPRESOLVED)
4466                 return;
4467         sg->sg_Flags |= SGF_TMPRESOLVED;
4468
4469         for (
4470                 d = getHead(&sg->sg_DeclList);
4471                 d;
4472                 d = getSucc(&sg->sg_DeclList, &d->d_Node)
4473         ) {
4474                 runesize_t offset = 0;
4475                 runesize_t goffset = 0;
4476
4477                 resolveStorageDeclExp(d, &offset, &goffset);
4478                 if (noffset < offset)
4479                         noffset = offset;
4480                 if (ngoffset < goffset)
4481                         ngoffset = goffset;
4482         }
4483         if ((d2 = sg->sg_CBase) != NULL) {
4484                 sg->sg_CBase = NULL;
4485                 while ((d = d2) != NULL) {
4486                         d2 = d->d_CNext;
4487                         d->d_CNext = sg->sg_CBase;
4488                         sg->sg_CBase = d;
4489                 }
4490         }
4491         if ((d2 = sg->sg_DBase) != NULL) {
4492                 sg->sg_DBase = NULL;
4493                 while ((d = d2) != NULL) {
4494                         d2 = d->d_DNext;
4495                         d->d_DNext = sg->sg_DBase;
4496                         sg->sg_DBase = d;
4497                 }
4498         }
4499         if ((d2 = sg->sg_GBase) != NULL) {
4500                 sg->sg_GBase = NULL;
4501                 while ((d = d2) != NULL) {
4502                         d2 = d->d_GNext;
4503                         d->d_GNext = sg->sg_GBase;
4504                         sg->sg_GBase = d;
4505                 }
4506         }
4507         if ((d2 = sg->sg_SRBase) != NULL) {
4508                 sg->sg_SRBase = NULL;
4509                 while ((d = d2) != NULL) {
4510                         d2 = d->d_SRNext;
4511                         d->d_SRNext = sg->sg_SRBase;
4512                         sg->sg_SRBase = d;
4513                 }
4514         }
4515         sg->sg_TmpBytes = noffset;
4516         sg->sg_GlobalTmpBytes = ngoffset;
4517 }