compiler/libec: Fixed warnings for related struct (and class:struct) classes
[sdk] / compiler / libec / src / pass3.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7 ///////////////// INSTANCE DECLARATION PASS ///////////////////////
8
9 // Returns true if we should add a * to the declarator
10 static int ReplaceClassSpec(OldList specs, Specifier spec, bool param)
11 {
12    if(spec.type == templateTypeSpecifier)
13    {
14       TemplateParameter parameter = spec.templateParameter;
15
16       if(!param && parameter.dataTypeString)
17       {
18          OldList * newSpecs = MkList();
19          Declarator decl = SpecDeclFromString(parameter.dataTypeString, newSpecs, null);
20          if(newSpecs->first)
21          {
22             Specifier newSpec = CopySpecifier(newSpecs->first);
23             *spec = *newSpec;
24             delete newSpec;
25          }
26          FreeList(newSpecs, FreeSpecifier);
27
28          if(decl)
29          {
30             bool isPointer = decl.type == pointerDeclarator;
31             if(decl)
32                FreeDeclarator(decl);
33             if(isPointer)
34                return 1;
35          }
36       }
37       else if(!param && parameter.dataType)
38       {
39          OldList * newSpecs = parameter.dataType.specifiers;
40          Declarator decl = parameter.dataType.decl;
41          if(newSpecs->first)
42          {
43             Specifier newSpec = CopySpecifier(newSpecs->first);
44             *spec = *newSpec;
45             delete newSpec;
46          }
47
48          if(decl)
49          {
50             bool isPointer = decl.type == pointerDeclarator;
51             if(isPointer)
52                return 1;
53          }
54       }
55       else
56       {
57          spec.type = nameSpecifier;
58          spec.name = CopyString("uint64");
59          spec.symbol = FindClass("uint64");
60       }
61    }
62
63    if(spec.type == nameSpecifier || spec.type == subClassSpecifier)
64    {
65       // TODO: Apply more care because nameSpecifier / subClassSpecifier use different parts of the union!
66       Symbol classSym = spec.symbol;
67       if(spec.type == subClassSpecifier)
68       {
69          classSym = FindClass("ecere::com::Class");
70       }
71
72       if(classSym)
73       {
74          Class _class = classSym.registered;
75
76          FreeSpecifierContents(spec);
77
78          spec.type = nameSpecifier;
79          if(_class && _class.type == structClass)
80          {
81             //Externalexternal;
82             char name[1024];
83             name[0] = 0;
84             FullClassNameCat(name, _class.fullName, false);
85             FreeSpecifierContents(spec);
86             spec.type = structSpecifier;
87             spec.baseSpecs = null;
88             spec.id = MkIdentifier(name);
89             spec.list = null;
90             spec.definitions = null;
91             spec.ctx = null;
92             spec.addNameSpace = false;
93          }
94          else if(_class && _class.type == noHeadClass)
95          {
96             char name[1024] = "";
97             FullClassNameCat(name, _class.fullName, false);
98             spec.type = structSpecifier;
99             spec.baseSpecs = null;
100             spec.id = MkIdentifier(name);
101             spec.list = null;
102             spec.definitions = null;
103             spec.ctx = null;
104             spec.addNameSpace = false;
105          }
106          else if(_class)
107          {
108             if((_class.type != systemClass ||
109                !strcmp(_class.fullName, "enum") ||
110                (_class.dataTypeString && !strcmp(_class.dataTypeString, "char *")) ||
111                //strcmp(_class.fullName, "bool") &&
112                !strcmp(_class.fullName, "uint64") ||
113                !strcmp(_class.fullName, "uint32") ||
114                !strcmp(_class.fullName, "uint16") ||
115                !strcmp(_class.fullName, "uintptr") ||
116                !strcmp(_class.fullName, "intptr") ||
117                !strcmp(_class.fullName, "uintsize") ||
118                !strcmp(_class.fullName, "intsize") ||
119                !strcmp(_class.fullName, "uint") ||
120                !strcmp(_class.fullName, "byte")))
121             {
122                if(_class.dataTypeString)
123                {
124                   if(!strcmp(_class.dataTypeString, "uint64") ||
125                      !strcmp(_class.dataTypeString, "uint32") ||
126                      !strcmp(_class.dataTypeString, "uint16") ||
127                      !strcmp(_class.dataTypeString, "uintptr") ||
128                      !strcmp(_class.dataTypeString, "intptr") ||
129                      !strcmp(_class.dataTypeString, "uintsize") ||
130                      !strcmp(_class.dataTypeString, "intsize") ||
131                      !strcmp(_class.dataTypeString, "uint") ||
132                      !strcmp(_class.dataTypeString, "byte"))
133                   {
134                      if(!_class.dataType)
135                         _class.dataType = ProcessTypeString(_class.dataTypeString, false);
136                      if(_class.dataType && _class.dataType.kind == classType)
137                         classSym = _class.dataType._class;
138                      else
139                         classSym = FindClass(_class.dataTypeString);
140                      _class = classSym ? classSym.registered : null;
141                   }
142
143                   spec.name = CopyString(!strcmp(_class.dataTypeString, "char *") ? "char" : _class.dataTypeString);
144                   spec.symbol = null;
145                }
146                else
147                {
148                   spec.name = CopyString(null);
149                   spec.symbol = null;
150                }
151             }
152             else if(!_class.base)
153             {
154                spec.type = baseSpecifier;
155                spec.specifier = VOID;
156                return 1;
157             }
158          }
159          else
160          {
161             spec.type = structSpecifier;
162             spec.id = MkIdentifier("__ecereNameSpace__ecere__com__Instance");
163             spec.list = null;
164             spec.baseSpecs = null;
165             spec.definitions = null;
166             spec.ctx = null;
167             spec.addNameSpace = false;
168          }
169
170          if(_class && _class.dataTypeString && !strcmp(_class.dataTypeString, "char *"))
171             return 1; //false;
172          if(!_class || _class.type == normalClass || _class.type == noHeadClass)
173             return 1;
174          else if(param && _class.type == structClass)
175             return 2;
176       }
177    }
178    else if(spec.type == baseSpecifier)
179    {
180       if(spec.specifier == ANY_OBJECT || spec.specifier == CLASS)
181       {
182          spec.specifier = CONST;
183          specs.Add(MkSpecifier(VOID));
184          return 1;
185       }
186    }
187    return 0;
188 }
189
190 static void ReplaceByInstancePtr(Specifier spec, Declarator * declPtr, int type)
191 {
192    Declarator decl = *declPtr;
193    if(decl && decl.type == pointerDeclarator)
194    {
195       // Pointers to simple classes shouldn't be added pointers
196       if(type == 2);
197       else
198       // Add pointer
199          decl.pointer.pointer = MkPointer(null, decl.pointer.pointer);
200    }
201    else
202    {
203       Declarator newDecl { };
204       if(decl)
205       {
206          *newDecl = *decl;
207          decl.declarator = newDecl;
208       }
209       else
210          decl = newDecl;
211       decl.type = pointerDeclarator;
212       decl.pointer.pointer = MkPointer(null, null);
213       *declPtr = decl;
214    }
215 }
216
217 static void InstDeclPassSpecifier(Specifier spec, bool byRefTypedObject)
218 {
219    switch(spec.type)
220    {
221       case baseSpecifier:
222          if(spec.specifier == TYPED_OBJECT)
223          {
224             spec.type = extendedSpecifier;
225             spec.extDecl = MkExtDeclString(CopyString(byRefTypedObject ?
226                "struct __ecereNameSpace__ecere__com__Class * class, void *" :
227                "struct __ecereNameSpace__ecere__com__Class * class, const void *"));
228          }
229          break;
230       case nameSpecifier:
231          break;
232       case enumSpecifier:
233       {
234          Enumerator e;
235          if(spec.list)
236          {
237             for(e = spec.list->first; e; e = e.next)
238             {
239
240             }
241          }
242          break;
243       }
244       case structSpecifier:
245       case unionSpecifier:
246       {
247          if(spec.definitions)
248          {
249             ClassDef def;
250             for(def = spec.definitions->first; def; def = def.next)
251                if(def.decl)
252                   InstDeclPassDeclaration(def.decl);
253          }
254          if(spec.id)
255             InstDeclPassIdentifier(spec.id);
256          break;
257       }
258       case extendedSpecifier:
259          if(spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s)
260          {
261             if(!strcmp(spec.extDecl.s, "dllexport"))
262             {
263                Specifier prevSpec;
264                delete spec.extDecl.s;
265                for(prevSpec = spec.prev; prevSpec; prevSpec = prevSpec.prev)
266                   if(prevSpec.type == baseSpecifier && prevSpec.specifier == EXTERN)
267                      break;
268                if(prevSpec)
269                {
270                   if(targetPlatform == win32)
271                      spec.extDecl.s = CopyString("__declspec(dllexport)");
272                   else
273                      spec.extDecl.s = CopyString("__attribute__ ((visibility(\"default\")))");
274                }
275                else
276                {
277                   if(targetPlatform == win32)
278                      spec.extDecl.s = CopyString("extern __declspec(dllexport)");
279                   else
280                      spec.extDecl.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
281                }
282             }
283             else if(!strcmp(spec.extDecl.s, "stdcall") || !strcmp(spec.extDecl.s, "_stdcall") ||
284                !strcmp(spec.extDecl.s, "__stdcall") || !strcmp(spec.extDecl.s, "__stdcall__"))
285             {
286                delete spec.extDecl.s;
287                if(targetPlatform == win32)
288                   spec.extDecl.s = CopyString("__attribute__((__stdcall__))");
289                else
290                   spec.extDecl.s = CopyString("");
291             }
292          }
293          break;
294    }
295 }
296
297 static void InstDeclPassDeclarator(Declarator decl)
298 {
299    switch(decl.type)
300    {
301       case structDeclarator:
302          if(decl.declarator)
303             InstDeclPassDeclarator(decl.declarator);
304          break;
305       case identifierDeclarator:
306       {
307          if(decl.identifier)
308             InstDeclPassIdentifier(decl.identifier);
309          break;
310       }
311       case bracketsDeclarator:
312          if(decl.declarator)
313             InstDeclPassDeclarator(decl.declarator);
314          break;
315       case arrayDeclarator:
316          if(decl.declarator)
317             InstDeclPassDeclarator(decl.declarator);
318          break;
319       case functionDeclarator:
320       {
321          if(decl.declarator)
322             InstDeclPassDeclarator(decl.declarator);
323          if(decl.function.parameters)
324          {
325             TypeName type;
326             if(decl.declarator)
327                InstDeclPassDeclarator(decl.declarator);
328             for(type = decl.function.parameters->first; type; type = type.next)
329             {
330                bool typedObject = false;
331                Specifier spec = null;
332                if(type.qualifiers)
333                {
334                   spec = (Specifier)type.qualifiers->first;
335                   if(spec && spec.type == nameSpecifier && !strcmp(spec.name, "class"))
336                      typedObject = true;
337                }
338
339                InstDeclPassTypeName(type, true);
340                if(typedObject)
341                {
342                   TypeName _class
343                   {
344                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
345                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
346                   };
347                   decl.function.parameters->Insert(spec.prev, _class);
348                }
349             }
350          }
351          break;
352       }
353       case pointerDeclarator:
354       case extendedDeclarator:
355       case extendedDeclaratorEnd:
356          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended)
357          {
358             if(decl.extended.extended.type == extDeclString && decl.extended.extended.s && !strcmp(decl.extended.extended.s, "dllexport"))
359             {
360                delete decl.extended.extended.s;
361                if(targetPlatform == win32)
362                   decl.extended.extended.s = CopyString("extern __declspec(dllexport)");
363                else
364                   decl.extended.extended.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
365             }
366             else if(decl.extended.extended.type == extDeclString && decl.extended.extended.s &&
367                (!strcmp(decl.extended.extended.s, "stdcall") || !strcmp(decl.extended.extended.s, "_stdcall") ||
368                !strcmp(decl.extended.extended.s, "__stdcall") || !strcmp(decl.extended.extended.s, "__stdcall__")))
369             {
370                delete decl.extended.extended.s;
371                if(targetPlatform == win32)
372                   decl.extended.extended.s = CopyString("__attribute__((__stdcall__))");
373                else
374                   decl.extended.extended.s = CopyString("");
375             }
376          }
377          if(decl.declarator)
378             InstDeclPassDeclarator(decl.declarator);
379          break;
380    }
381 }
382
383 /*static */void InstDeclPassTypeName(TypeName type, bool param)
384 {
385    if(type.qualifiers)
386    {
387       Specifier spec;
388       for(spec = type.qualifiers->first; spec; spec = spec.next)
389       {
390          int result;
391          if((result = ReplaceClassSpec(type.qualifiers, spec, param)))
392             ReplaceByInstancePtr(spec, &type.declarator, result);
393          else
394          {
395             Symbol classSym = (spec.type == nameSpecifier) ? spec.symbol /*FindClass(spec.name)*/ : null;
396             if(type.classObjectType && (!classSym || (classSym && classSym.registered &&
397                (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass))))
398                ReplaceByInstancePtr(spec, &type.declarator, 2);
399          }
400          InstDeclPassSpecifier(spec, type.declarator && type.declarator.type == pointerDeclarator);
401       }
402    }
403    if(type.declarator)
404       InstDeclPassDeclarator(type.declarator);
405 }
406
407 static void InstDeclPassIdentifier(Identifier id)
408 {
409    if(strchr(id.string, ':'))
410    {
411       char newID[1024];
412       int c;
413       char ch;
414       int len;
415       strcpy(newID, "__ecereNameSpace__");
416       len = strlen(newID);
417
418       for(c = 0; (ch = id.string[c]); c++)
419       {
420          if(ch == ':') ch = '_';
421
422          newID[len++] = ch;
423       }
424       newID[len] = 0;
425       delete id.string;
426       id.string = CopyString(newID);
427    }
428 }
429
430 static bool IsVoidPtrCast(TypeName typeName)
431 {
432    bool result = false;
433    Declarator d = typeName.declarator;
434    if(d && d.type == pointerDeclarator && d.pointer.pointer == null)
435    {
436       if(typeName.qualifiers)
437       {
438          Specifier s;
439          for(s = typeName.qualifiers->first; s; s = s.next)
440          {
441             if(s.type == baseSpecifier && s.specifier == VOID)
442                result = true;
443          }
444       }
445    }
446    return result;
447 }
448
449 static void InstDeclPassExpression(Expression exp)
450 {
451    switch(exp.type)
452    {
453       case identifierExp:
454       {
455          if(exp.identifier)
456             InstDeclPassIdentifier(exp.identifier);
457          break;
458       }
459       case constantExp:
460          break;
461       case stringExp:
462          break;
463       case opExp:
464          if(exp.op.exp1)
465             InstDeclPassExpression(exp.op.exp1);
466          if(exp.op.exp2)
467             InstDeclPassExpression(exp.op.exp2);
468          break;
469       case extensionExpressionExp:
470       case bracketsExp:
471       {
472          Expression e;
473          for(e = exp.list->first; e; e = e.next)
474             InstDeclPassExpression(e);
475          break;
476       }
477       case indexExp:
478       {
479          Expression e;
480          InstDeclPassExpression(exp.index.exp);
481          for(e = exp.index.index->first; e; e = e.next)
482             InstDeclPassExpression(e);
483          break;
484       }
485       case callExp:
486       {
487          Expression e;
488          InstDeclPassExpression(exp.call.exp);
489          if(exp.call.arguments)
490          {
491             for(e = exp.call.arguments->first; e; e = e.next)
492             {
493                Type src = e.expType;
494
495                InstDeclPassExpression(e);
496
497                if(src && (src.kind == templateType || src.kind == classType))
498                {
499                   if(e.type != castExp || !IsVoidPtrCast(e.cast.typeName))
500                   {
501                      if(src) src.refCount++;
502                      if(src.kind == templateType)
503                      {
504                         if(src.templateParameter && src.templateParameter.type == type)
505                         {
506                            Type newType = null;
507                            if(src.templateParameter.dataTypeString)
508                               newType = ProcessTypeString(src.templateParameter.dataTypeString, false);
509                            else if(src.templateParameter.dataType)
510                               newType = ProcessType(src.templateParameter.dataType.specifiers, src.templateParameter.dataType.decl);
511                            if(newType)
512                            {
513                               FreeType(src);
514                               src = newType;
515                            }
516                         }
517                      }
518                      if(src && src.kind == classType && src._class)
519                      {
520                         Class sc = src._class.registered;
521                         if(sc && (sc.type == structClass || sc.type == noHeadClass))
522                         {
523                            Type dest = e.destType;
524                            if(dest && (dest.kind == templateType || dest.kind == classType))
525                            {
526                               if(dest) dest.refCount++;
527
528                               if(dest.templateParameter && dest.templateParameter.type == type)
529                               {
530                                  Type newType = null;
531                                  if(dest.templateParameter.dataTypeString)
532                                     newType = ProcessTypeString(dest.templateParameter.dataTypeString, false);
533                                  else if(dest.templateParameter.dataType)
534                                     newType = ProcessType(dest.templateParameter.dataType.specifiers, dest.templateParameter.dataType.decl);
535                                  if(newType)
536                                  {
537                                     FreeType(dest);
538                                     dest = newType;
539                                  }
540                               }
541                               if(!dest.passAsTemplate && dest.kind == classType && dest._class && dest._class.registered)
542                               {
543                                  Class dc = dest._class.registered;
544                                  if(sc.templateClass) sc = sc.templateClass;
545                                  if(dc.templateClass) dc = dc.templateClass;
546                                  if(dc.base && (sc != dc || sc.base.type == structClass))
547                                  {
548                                     e.cast.exp = CopyExpContents(e);
549                                     e.type = castExp;
550                                     e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
551                                  }
552                               }
553                               FreeType(dest);
554                            }
555                         }
556                      }
557                   }
558                   FreeType(src);
559                }
560             }
561          }
562          break;
563       }
564       case memberExp:
565       {
566          if(exp.member.exp)
567             InstDeclPassExpression(exp.member.exp);
568          break;
569       }
570       case pointerExp:
571       {
572          if(exp.member.exp)
573             InstDeclPassExpression(exp.member.exp);
574          break;
575       }
576       case typeSizeExp:
577          InstDeclPassTypeName(exp.typeName, false);
578          break;
579       case castExp:
580       {
581          Type type = exp.expType;
582          // Remove casts to simple structs... (Watch out for pointers later...)
583          if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass && !exp.needCast)
584          {
585             Expression castExp = exp.cast.exp;
586             Expression prev = exp.prev, next = exp.next;
587             exp.cast.exp = null;
588             FreeExpContents(exp);
589             FreeType(exp.expType);
590             FreeType(exp.destType);
591             *exp = *castExp;
592             delete castExp;
593             exp.prev = prev;
594             exp.next = next;
595             InstDeclPassExpression(exp);
596          }
597          else
598          {
599             InstDeclPassTypeName(exp.cast.typeName, exp.usage.usageArg /*false*/);
600             if(exp.cast.exp)
601                InstDeclPassExpression(exp.cast.exp);
602          }
603          break;
604       }
605       case conditionExp:
606       {
607          Expression e;
608          InstDeclPassExpression(exp.cond.cond);
609          for(e = exp.cond.exp->first; e; e = e.next)
610             InstDeclPassExpression(e);
611          InstDeclPassExpression(exp.cond.elseExp);
612          break;
613       }
614       case extensionCompoundExp:
615       {
616          InstDeclPassStatement(exp.compound);
617          break;
618       }
619       case vaArgExp:
620       {
621          InstDeclPassExpression(exp.vaArg.exp);
622          break;
623       }
624       case extensionInitializerExp:
625       {
626          InstDeclPassTypeName(exp.initializer.typeName, false);
627          InstDeclPassInitializer(exp.initializer.initializer);
628          break;
629       }
630    }
631 }
632
633 static void InstDeclPassInitializer(Initializer init)
634 {
635    switch(init.type)
636    {
637       case expInitializer:
638          if(init.exp)
639             InstDeclPassExpression(init.exp);
640          break;
641       case listInitializer:
642       {
643          Initializer i;
644          for(i = init.list->first; i; i = i.next)
645             InstDeclPassInitializer(i);
646          break;
647       }
648    }
649 }
650
651 static void InstDeclPassDeclaration(Declaration decl)
652 {
653    switch(decl.type)
654    {
655       case initDeclaration:
656       {
657          if(decl.specifiers)
658          {
659             Specifier spec;
660             for(spec = decl.specifiers->first; spec; spec = spec.next)
661             {
662                int type;
663                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
664                {
665                   InitDeclarator d;
666                   if(decl.declarators)
667                   {
668                      for(d = decl.declarators->first; d; d = d.next)
669                         ReplaceByInstancePtr(spec, &d.declarator, type);
670                   }
671                }
672                InstDeclPassSpecifier(spec, false);
673             }
674          }
675          if(decl.declarators)
676          {
677             InitDeclarator d;
678             for(d = decl.declarators->first; d; d = d.next)
679             {
680                InstDeclPassDeclarator(d.declarator);
681                if(d.initializer)
682                   InstDeclPassInitializer(d.initializer);
683             }
684          }
685          break;
686       }
687       case structDeclaration:
688       {
689          if(decl.specifiers)
690          {
691             Specifier spec;
692             for(spec = decl.specifiers->first; spec; spec = spec.next)
693             {
694                int type;
695                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
696                {
697                   if(decl.declarators)
698                   {
699                      Declarator d;
700                      for(d = decl.declarators->first; d; d = d.next)
701                         ReplaceByInstancePtr(spec, &d, type);
702                   }
703                }
704                InstDeclPassSpecifier(spec, false);
705             }
706          }
707
708          if(decl.declarators)
709          {
710             Declarator d;
711             for(d = decl.declarators->first; d; d = d.next)
712                InstDeclPassDeclarator(d);
713          }
714          break;
715       }
716       // This should be removed by now?
717       case instDeclaration:
718          // InstDeclPassInstantiation(decl.inst);
719          break;
720    }
721 }
722
723 static void InstDeclPassStatement(Statement stmt)
724 {
725    switch(stmt.type)
726    {
727       case badDeclarationStmt:
728          if(stmt.decl)
729             InstDeclPassDeclaration(stmt.decl);
730          break;
731       case labeledStmt:
732          InstDeclPassStatement(stmt.labeled.stmt);
733          break;
734       case caseStmt:
735          // This expression should be constant...
736          if(stmt.caseStmt.exp)
737             InstDeclPassExpression(stmt.caseStmt.exp);
738          if(stmt.caseStmt.stmt)
739             InstDeclPassStatement(stmt.caseStmt.stmt);
740          break;
741       case compoundStmt:
742       {
743          Declaration decl;
744          Statement s;
745          Context prevContext = curContext;
746
747          if(!stmt.compound.isSwitch)
748             curContext = stmt.compound.context;
749
750          if(stmt.compound.declarations)
751          {
752             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
753                InstDeclPassDeclaration(decl);
754          }
755          if(stmt.compound.statements)
756          {
757             for(s = stmt.compound.statements->first; s; s = s.next)
758                InstDeclPassStatement(s);
759          }
760          curContext = prevContext;
761          break;
762       }
763       case expressionStmt:
764       {
765          if(stmt.expressions)
766          {
767             Expression exp;
768             for(exp = stmt.expressions->first; exp; exp = exp.next)
769                InstDeclPassExpression(exp);
770          }
771          break;
772       }
773       case ifStmt:
774       {
775          if(stmt.ifStmt.exp)
776          {
777             Expression exp;
778             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
779                InstDeclPassExpression(exp);
780          }
781          if(stmt.ifStmt.stmt)
782             InstDeclPassStatement(stmt.ifStmt.stmt);
783          if(stmt.ifStmt.elseStmt)
784             InstDeclPassStatement(stmt.ifStmt.elseStmt);
785          break;
786       }
787       case switchStmt:
788       {
789          Expression exp;
790          if(stmt.switchStmt.exp)
791          {
792             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
793                InstDeclPassExpression(exp);
794          }
795          InstDeclPassStatement(stmt.switchStmt.stmt);
796          break;
797       }
798       case whileStmt:
799       {
800          Expression exp;
801          if(stmt.whileStmt.exp)
802          {
803             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
804                InstDeclPassExpression(exp);
805          }
806          InstDeclPassStatement(stmt.whileStmt.stmt);
807          break;
808       }
809       case doWhileStmt:
810       {
811          if(stmt.doWhile.exp)
812          {
813             Expression exp;
814             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
815                InstDeclPassExpression(exp);
816          }
817          if(stmt.doWhile.stmt)
818             InstDeclPassStatement(stmt.doWhile.stmt);
819          break;
820       }
821       case forStmt:
822       {
823          Expression exp;
824          if(stmt.forStmt.init)
825             InstDeclPassStatement(stmt.forStmt.init);
826          if(stmt.forStmt.check)
827             InstDeclPassStatement(stmt.forStmt.check);
828          if(stmt.forStmt.increment)
829          {
830             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
831                InstDeclPassExpression(exp);
832          }
833          if(stmt.forStmt.stmt)
834             InstDeclPassStatement(stmt.forStmt.stmt);
835          break;
836       }
837       case gotoStmt:
838          break;
839       case continueStmt:
840          break;
841       case breakStmt:
842          break;
843       case returnStmt:
844       {
845          Expression exp;
846          if(stmt.expressions)
847          {
848             for(exp = stmt.expressions->first; exp; exp = exp.next)
849                InstDeclPassExpression(exp);
850          }
851          break;
852       }
853       case asmStmt:
854       {
855          AsmField field;
856          if(stmt.asmStmt.inputFields)
857          {
858             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
859                if(field.expression)
860                   InstDeclPassExpression(field.expression);
861          }
862          if(stmt.asmStmt.outputFields)
863          {
864             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
865                if(field.expression)
866                   InstDeclPassExpression(field.expression);
867          }
868          if(stmt.asmStmt.clobberedFields)
869          {
870             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
871                if(field.expression)
872                   InstDeclPassExpression(field.expression);
873          }
874          break;
875       }
876    }
877 }
878
879 public void ProcessInstanceDeclarations()
880 {
881    External external;
882    curContext = globalContext;
883    for(external = ast->first; external; external = external.next)
884    {
885       curExternal = external;
886       if(external.type == functionExternal)
887       {
888          FunctionDefinition func = external.function;
889          if(func.specifiers)
890          {
891             Specifier spec;
892             for(spec = func.specifiers->first; spec; spec = spec.next)
893             {
894                int type;
895                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
896                   ReplaceByInstancePtr(spec, &func.declarator, type);
897                InstDeclPassSpecifier(spec, false);
898             }
899          }
900          InstDeclPassDeclarator(func.declarator);
901          if(func.body)
902             InstDeclPassStatement(func.body);
903       }
904       else if(external.type == declarationExternal)
905       {
906          if(external.declaration)
907             InstDeclPassDeclaration(external.declaration);
908       }
909    }
910 }