compiler/libec: Casts where function pointers are expected
[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 && !d.pointer.pointer.pointer)
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 && src.templateParameter && src.templateParameter.type == type)
503                      {
504                         Type newType = null;
505                         if(src.templateParameter.dataTypeString)
506                            newType = ProcessTypeString(src.templateParameter.dataTypeString, false);
507                         else if(src.templateParameter.dataType)
508                            newType = ProcessType(src.templateParameter.dataType.specifiers, src.templateParameter.dataType.decl);
509                         if(newType)
510                         {
511                            FreeType(src);
512                            src = newType;
513                         }
514                      }
515                      if(src && src.kind == classType && src._class)
516                      {
517                         Class sc = src._class.registered;
518                         if(sc && (sc.type == structClass || sc.type == noHeadClass))
519                         {
520                            Type dest = e.destType;
521                            if(dest && (dest.kind == templateType || dest.kind == classType))
522                            {
523                               if(dest) dest.refCount++;
524
525                               if(dest.kind == templateType && dest.templateParameter && dest.templateParameter.type == type)
526                               {
527                                  Type newType = null;
528                                  if(dest.templateParameter.dataTypeString)
529                                     newType = ProcessTypeString(dest.templateParameter.dataTypeString, false);
530                                  else if(dest.templateParameter.dataType)
531                                     newType = ProcessType(dest.templateParameter.dataType.specifiers, dest.templateParameter.dataType.decl);
532                                  if(newType)
533                                  {
534                                     FreeType(dest);
535                                     dest = newType;
536                                  }
537                               }
538                               if(!dest.passAsTemplate && dest.kind == classType && dest._class && dest._class.registered)
539                               {
540                                  Class dc = dest._class.registered;
541                                  if(sc.templateClass) sc = sc.templateClass;
542                                  if(dc.templateClass) dc = dc.templateClass;
543                                  if(dc.base && sc != dc)
544                                  {
545                                     e.cast.exp = MoveExpContents(e);
546                                     e.type = castExp;
547                                     e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
548                                  }
549                               }
550                               FreeType(dest);
551                            }
552                         }
553                      }
554                   }
555                   FreeType(src);
556                }
557             }
558          }
559          break;
560       }
561       case memberExp:
562       {
563          if(exp.member.exp)
564             InstDeclPassExpression(exp.member.exp);
565          break;
566       }
567       case pointerExp:
568       {
569          if(exp.member.exp)
570             InstDeclPassExpression(exp.member.exp);
571          break;
572       }
573       case typeSizeExp:
574          InstDeclPassTypeName(exp.typeName, false);
575          break;
576       case castExp:
577       {
578          Type type = exp.expType;
579          // Remove casts to simple structs... (Watch out for pointers later...)
580          if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass && !exp.needCast)
581          {
582             Expression castExp = exp.cast.exp;
583             Expression prev = exp.prev, next = exp.next;
584             exp.cast.exp = null;
585             FreeExpContents(exp);
586             FreeType(exp.expType);
587             FreeType(exp.destType);
588             *exp = *castExp;
589             delete castExp;
590             exp.prev = prev;
591             exp.next = next;
592             InstDeclPassExpression(exp);
593          }
594          else
595          {
596             InstDeclPassTypeName(exp.cast.typeName, exp.usage.usageArg /*false*/);
597             if(exp.cast.exp)
598                InstDeclPassExpression(exp.cast.exp);
599          }
600          break;
601       }
602       case conditionExp:
603       {
604          Expression e;
605          InstDeclPassExpression(exp.cond.cond);
606          for(e = exp.cond.exp->first; e; e = e.next)
607             InstDeclPassExpression(e);
608          InstDeclPassExpression(exp.cond.elseExp);
609          break;
610       }
611       case extensionCompoundExp:
612       {
613          InstDeclPassStatement(exp.compound);
614          break;
615       }
616       case vaArgExp:
617       {
618          InstDeclPassExpression(exp.vaArg.exp);
619          break;
620       }
621       case extensionInitializerExp:
622       {
623          InstDeclPassTypeName(exp.initializer.typeName, false);
624          InstDeclPassInitializer(exp.initializer.initializer);
625          break;
626       }
627    }
628 }
629
630 static void InstDeclPassInitializer(Initializer init)
631 {
632    switch(init.type)
633    {
634       case expInitializer:
635          if(init.exp)
636             InstDeclPassExpression(init.exp);
637          break;
638       case listInitializer:
639       {
640          Initializer i;
641          for(i = init.list->first; i; i = i.next)
642             InstDeclPassInitializer(i);
643          break;
644       }
645    }
646 }
647
648 static void InstDeclPassDeclaration(Declaration decl)
649 {
650    switch(decl.type)
651    {
652       case initDeclaration:
653       {
654          if(decl.specifiers)
655          {
656             Specifier spec;
657             for(spec = decl.specifiers->first; spec; spec = spec.next)
658             {
659                int type;
660                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
661                {
662                   InitDeclarator d;
663                   if(decl.declarators)
664                   {
665                      for(d = decl.declarators->first; d; d = d.next)
666                         ReplaceByInstancePtr(spec, &d.declarator, type);
667                   }
668                }
669                InstDeclPassSpecifier(spec, false);
670             }
671          }
672          if(decl.declarators)
673          {
674             InitDeclarator d;
675             for(d = decl.declarators->first; d; d = d.next)
676             {
677                InstDeclPassDeclarator(d.declarator);
678                if(d.initializer)
679                   InstDeclPassInitializer(d.initializer);
680             }
681          }
682          break;
683       }
684       case structDeclaration:
685       {
686          if(decl.specifiers)
687          {
688             Specifier spec;
689             for(spec = decl.specifiers->first; spec; spec = spec.next)
690             {
691                int type;
692                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
693                {
694                   if(decl.declarators)
695                   {
696                      Declarator d;
697                      for(d = decl.declarators->first; d; d = d.next)
698                         ReplaceByInstancePtr(spec, &d, type);
699                   }
700                }
701                InstDeclPassSpecifier(spec, false);
702             }
703          }
704
705          if(decl.declarators)
706          {
707             Declarator d;
708             for(d = decl.declarators->first; d; d = d.next)
709                InstDeclPassDeclarator(d);
710          }
711          break;
712       }
713       // This should be removed by now?
714       case instDeclaration:
715          // InstDeclPassInstantiation(decl.inst);
716          break;
717    }
718 }
719
720 static void InstDeclPassStatement(Statement stmt)
721 {
722    switch(stmt.type)
723    {
724       case badDeclarationStmt:
725          if(stmt.decl)
726             InstDeclPassDeclaration(stmt.decl);
727          break;
728       case labeledStmt:
729          InstDeclPassStatement(stmt.labeled.stmt);
730          break;
731       case caseStmt:
732          // This expression should be constant...
733          if(stmt.caseStmt.exp)
734             InstDeclPassExpression(stmt.caseStmt.exp);
735          if(stmt.caseStmt.stmt)
736             InstDeclPassStatement(stmt.caseStmt.stmt);
737          break;
738       case compoundStmt:
739       {
740          Declaration decl;
741          Statement s;
742          Context prevContext = curContext;
743
744          if(!stmt.compound.isSwitch)
745             curContext = stmt.compound.context;
746
747          if(stmt.compound.declarations)
748          {
749             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
750                InstDeclPassDeclaration(decl);
751          }
752          if(stmt.compound.statements)
753          {
754             for(s = stmt.compound.statements->first; s; s = s.next)
755                InstDeclPassStatement(s);
756          }
757          curContext = prevContext;
758          break;
759       }
760       case expressionStmt:
761       {
762          if(stmt.expressions)
763          {
764             Expression exp;
765             for(exp = stmt.expressions->first; exp; exp = exp.next)
766                InstDeclPassExpression(exp);
767          }
768          break;
769       }
770       case ifStmt:
771       {
772          if(stmt.ifStmt.exp)
773          {
774             Expression exp;
775             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
776                InstDeclPassExpression(exp);
777          }
778          if(stmt.ifStmt.stmt)
779             InstDeclPassStatement(stmt.ifStmt.stmt);
780          if(stmt.ifStmt.elseStmt)
781             InstDeclPassStatement(stmt.ifStmt.elseStmt);
782          break;
783       }
784       case switchStmt:
785       {
786          Expression exp;
787          if(stmt.switchStmt.exp)
788          {
789             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
790                InstDeclPassExpression(exp);
791          }
792          InstDeclPassStatement(stmt.switchStmt.stmt);
793          break;
794       }
795       case whileStmt:
796       {
797          Expression exp;
798          if(stmt.whileStmt.exp)
799          {
800             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
801                InstDeclPassExpression(exp);
802          }
803          InstDeclPassStatement(stmt.whileStmt.stmt);
804          break;
805       }
806       case doWhileStmt:
807       {
808          if(stmt.doWhile.exp)
809          {
810             Expression exp;
811             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
812                InstDeclPassExpression(exp);
813          }
814          if(stmt.doWhile.stmt)
815             InstDeclPassStatement(stmt.doWhile.stmt);
816          break;
817       }
818       case forStmt:
819       {
820          Expression exp;
821          if(stmt.forStmt.init)
822             InstDeclPassStatement(stmt.forStmt.init);
823          if(stmt.forStmt.check)
824             InstDeclPassStatement(stmt.forStmt.check);
825          if(stmt.forStmt.increment)
826          {
827             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
828                InstDeclPassExpression(exp);
829          }
830          if(stmt.forStmt.stmt)
831             InstDeclPassStatement(stmt.forStmt.stmt);
832          break;
833       }
834       case gotoStmt:
835          break;
836       case continueStmt:
837          break;
838       case breakStmt:
839          break;
840       case returnStmt:
841       {
842          Expression exp;
843          if(stmt.expressions)
844          {
845             for(exp = stmt.expressions->first; exp; exp = exp.next)
846                InstDeclPassExpression(exp);
847          }
848          break;
849       }
850       case asmStmt:
851       {
852          AsmField field;
853          if(stmt.asmStmt.inputFields)
854          {
855             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
856                if(field.expression)
857                   InstDeclPassExpression(field.expression);
858          }
859          if(stmt.asmStmt.outputFields)
860          {
861             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
862                if(field.expression)
863                   InstDeclPassExpression(field.expression);
864          }
865          if(stmt.asmStmt.clobberedFields)
866          {
867             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
868                if(field.expression)
869                   InstDeclPassExpression(field.expression);
870          }
871          break;
872       }
873    }
874 }
875
876 public void ProcessInstanceDeclarations()
877 {
878    External external;
879    curContext = globalContext;
880    for(external = ast->first; external; external = external.next)
881    {
882       curExternal = external;
883       if(external.type == functionExternal)
884       {
885          FunctionDefinition func = external.function;
886          if(func.specifiers)
887          {
888             Specifier spec;
889             for(spec = func.specifiers->first; spec; spec = spec.next)
890             {
891                int type;
892                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
893                   ReplaceByInstancePtr(spec, &func.declarator, type);
894                InstDeclPassSpecifier(spec, false);
895             }
896          }
897          InstDeclPassDeclarator(func.declarator);
898          if(func.body)
899             InstDeclPassStatement(func.body);
900       }
901       else if(external.type == declarationExternal)
902       {
903          if(external.declaration)
904             InstDeclPassDeclaration(external.declaration);
905       }
906    }
907 }