c3ebc36758a9c9bf040249adbf249173f4e68c14
[sdk] / compiler / libec / src / pass2.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7 static Statement curCompound;
8
9 static void _FixRefExp(Expression * expPtr, Expression * memberExpPtr)
10 {
11
12    Expression memberExp = *memberExpPtr;
13    if(memberExp && memberExp.type == ExpressionType::memberExp &&
14       memberExp.member.exp && (memberExp.member.exp.type == bracketsExp || memberExp.member.exp.type == extensionExpressionExp))
15    {
16       Expression bracketExp = memberExp.member.exp;
17       Expression idExp = bracketExp.list->last;
18
19       if(idExp && idExp.type == identifierExp)
20       {
21          Expression newExp = null;
22          Expression exp = *expPtr;
23
24          // opExp ( memberExp ( bracketsExp ( identifierExp ) ) )
25          // bracketsExp ( opExp ( memberExp ( identifierExp ) ) )
26
27          *memberExpPtr = null;
28          newExp = CopyExpression(exp);
29          FreeExpContents(exp);
30
31          *(Expression *)((byte *)newExp + (uint)((byte *)memberExpPtr - (byte *)exp)) = memberExp;
32
33          memberExp.member.exp = idExp;
34
35          exp.type = bracketsExp;
36          exp.list = bracketExp.list;
37          bracketExp.list = null;
38
39          exp.list->Remove(idExp);
40          exp.list->Add(newExp);
41          FreeExpression(bracketExp);
42
43          *expPtr = exp; //FixRefExp(newExp);      // TESTING THIS: exp was not used!
44       }
45    }
46    else if(*expPtr && (*expPtr).type == opExp && (*expPtr).op.op == '&' && !(*expPtr).op.exp1 &&
47       memberExp && (memberExp.type == bracketsExp || memberExp.type == extensionExpressionExp) && memberExp.list && memberExp.list->count > 1)
48    {
49       Expression newExp = null;
50       Expression exp = *expPtr;
51
52       *memberExpPtr = null;
53       newExp = CopyExpression(exp);
54       *(Expression *)((byte *)newExp + (uint)((byte *)memberExpPtr - (byte *)exp)) = memberExp.list->last;
55
56       exp.type = bracketsExp;
57       exp.list = memberExp.list;
58       memberExp.list = null;
59
60       exp.list->Remove(exp.list->last);
61       exp.list->Add(newExp);
62       FreeExpression(memberExp);
63
64       *expPtr = newExp; //FixRefExp(newExp);
65    }
66 }
67
68 static Expression FixRefExp(Expression exp)
69 {
70    if(exp.type == opExp)
71    {
72       _FixRefExp(&exp, &exp.op.exp1);
73       _FixRefExp(&exp, &exp.op.exp2);
74    }
75    else if(exp.type == indexExp)
76       _FixRefExp(&exp, &exp.index.exp);
77    else if(exp.type == memberExp)
78       _FixRefExp(&exp, &exp.member.exp);
79    return exp;
80 }
81
82 static Expression FixReference(Expression e, bool wantReference)
83 {
84    if(e.expType && e.type != constantExp)
85    {
86       Type type = e.expType;
87       bool isPointer = false;
88       /*
89       if(type.kind == TypePointer && type.type && type.type.kind == classType)
90       {
91          type = type.type;
92          isPointer = true;
93       }
94       */
95
96       if(type.kind == classType) // || type.kind == TypeInt)
97       {
98          Class _class = type._class ? type._class.registered : null;
99          // TOLOOKINTO: What was systemClass used for here? Exclude "typed_object"...
100          // TOFIX: In which case with systemClass do we actually want this to come here? Can't think of any!
101          if(_class && ((_class.type == structClass && !type.declaredWithStruct) || _class.type == noHeadClass ||
102            (_class.type == systemClass && _class.base &&
103            strcmp(_class.fullName, "uintptr") &&
104            strcmp(_class.fullName, "intptr") &&
105            strcmp(_class.fullName, "uintsize") &&
106            strcmp(_class.fullName, "intsize"))))
107          {
108             // if(wantReference != ((_class.type == systemClass) ? false : e.byReference))
109             if(wantReference != (e.byReference || isPointer))
110             {
111                Expression exp = e;
112                for(;;)
113                {
114                   if(exp.type == bracketsExp || exp.type == extensionExpressionExp)
115                   {
116                      if(exp.list)
117                      {
118                         exp.byReference = wantReference;
119                         exp = exp.list->last;
120                      }
121                      else
122                         break;
123                   }
124                   else if(exp.type == castExp)
125                   {
126                      exp.byReference = wantReference;
127                      exp = exp.cast.exp;
128                   }
129                   else if(exp.type == conditionExp)
130                   {
131                      if(exp.cond.exp->last)
132                         FixReference(exp.cond.exp->last, wantReference);
133                      FixReference(exp.cond.elseExp, wantReference);
134                      break;
135                   }
136                   else
137                   {
138                      if(wantReference != (exp.byReference || isPointer))
139                      {
140                         Expression newExp { };
141                         *newExp = *exp;
142                         newExp.prev = null;
143                         newExp.next = null;
144
145                         if(exp.destType) exp.destType.refCount++;
146                         if(exp.expType) exp.expType.refCount++;
147
148                         exp.type = opExp;
149                         exp.op.exp1 = null;
150                         exp.op.exp2 = newExp;
151                         if(wantReference)
152                            exp.op.op = '&';
153                         else
154                            exp.op.op = '*';
155
156                         e.byReference = wantReference;
157                         exp.byReference = wantReference;
158                      }
159                      break;
160                   }
161                }
162             }
163          }
164       }
165    }
166    e = FixRefExp(e);
167    return e;
168 }
169
170 static Expression GetInnerExp(Expression exp)
171 {
172    Expression e = exp;
173    while(e && (e.type == bracketsExp || e.type == castExp))
174    {
175       if(e.type == bracketsExp)
176          e = e.list ? e.list->last : null;
177       else if(e.type == castExp)
178          e = e.cast.exp;
179    }
180    return e;
181 }
182
183 Expression GetNonBracketsExp(Expression exp)
184 {
185    Expression e = exp;
186    while(e && e.type == bracketsExp)
187       e = e.list ? e.list->last : null;
188    return e;
189 }
190
191 static bool FixMember(Expression exp)
192 {
193    bool byReference = false;
194    for(;exp;)
195    {
196       if(exp.type == bracketsExp || exp.type == extensionExpressionExp)
197       {
198          if(exp.list->count > 1)
199             byReference = true;
200          exp = exp.list->last;
201       }
202       else if(exp.type == castExp)
203       {
204          exp = exp.cast.exp;
205       }
206       else
207       {
208          if(byReference)
209             FixReference(exp, true);
210          else
211             byReference = exp.byReference;
212          break;
213       }
214    }
215    return byReference;
216 }
217
218 static void ProcessExpression(Expression exp)
219 {
220    Location oldyylloc = yylloc;
221 #ifdef _DEBUG
222    char debugExpString[1024] = "";
223    PrintExpression(exp, debugExpString);
224 #endif
225
226    // Testing this here
227    yylloc = exp.loc;
228
229    switch(exp.type)
230    {
231       case identifierExp:
232       {
233          if(exp.expType && exp.expType.kind == methodType)
234          {
235             Class _class = exp.expType.methodClass;
236             Method method = exp.expType.method;
237             if(method.type == virtualMethod)
238             {
239                char name[1024];
240                TypeName typeName;
241                Declarator decl;
242                OldList * specs = MkList();
243                strcpy(name, "__ecereVMethodID_");
244                FullClassNameCat(name, method._class.fullName, false);
245                strcat(name, "_");
246                strcat(name, method.name);
247
248                DeclareMethod(curExternal, method, name);
249
250                // Cast function to its type
251                decl = SpecDeclFromString(method.dataTypeString, specs, MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), null)));
252                if(!method.dataType.staticMethod)
253                {
254                   Declarator funcDecl = GetFuncDecl(decl);
255
256                   if(!funcDecl.function.parameters)
257                      funcDecl.function.parameters = MkList();
258                   {
259                      TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
260                      Specifier firstSpec = firstParam ? firstParam.qualifiers->first : null;
261
262                      if(firstParam && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
263                         funcDecl.function.parameters->Remove(funcDecl.function.parameters->first);
264                   }
265
266                   funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(
267                      /*MkClassName*/MkSpecifierName(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)), null));
268                }
269
270                typeName = MkTypeName(specs, decl);
271
272                if(_class)
273                {
274                   char className[1024];
275                   // Need the class itself here...
276                   strcpy(className, "__ecereClass_");
277                   FullClassNameCat(className, _class.fullName, true);
278
279                   if(!_class.symbol)
280                      _class.symbol = FindClass(_class.fullName);
281                   DeclareClass(curExternal, _class.symbol, className);
282
283                   if(exp.identifier)
284                      FreeIdentifier(exp.identifier);
285                   exp.type = bracketsExp;
286                   exp.list = MkListOne(MkExpCast(typeName,
287                      MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl")),
288                      MkListOne(MkExpIdentifier(MkIdentifier(name))))));
289                }
290             }
291             else
292             {
293                char name[1024];
294                strcpy(name, "__ecereMethod_");
295                FullClassNameCat(name, method._class.fullName, false);
296                strcat(name, "_");
297                strcat(name, method.name);
298
299                delete exp.identifier.string;
300                FreeSpecifier(exp.identifier._class);
301
302                exp.identifier._class = null;
303                exp.identifier.string = CopyString(name);
304                DeclareMethod(curExternal, method, name);
305             }
306          }
307          /*
308          if(exp.usage & USAGE_MEMBER)
309             FixReference(exp, true);
310          */
311          break;
312       }
313       case constantExp:
314          break;
315       case stringExp:
316          break;
317       case newExp:
318       case new0Exp:
319       case renewExp:
320       case renew0Exp:
321       {
322          OldList * args = MkList();
323
324          if(exp.type == renewExp || exp.type == renew0Exp)
325             ListAdd(args, exp._renew.exp);
326
327          ListAdd(args, MkExpOp(MkExpTypeSize(exp._new.typeName), '*', MkExpBrackets(MkListOne(exp._new.size))));
328
329          switch(exp.type)
330          {
331             case newExp:   exp.call.exp = QMkExpId("ecere::com::eSystem_New"); DeclareFunctionUtil(curExternal, "eSystem_New"); break;
332             case new0Exp:  exp.call.exp = QMkExpId("ecere::com::eSystem_New0"); DeclareFunctionUtil(curExternal, "eSystem_New0"); break;
333             case renewExp: exp.call.exp = QMkExpId("ecere::com::eSystem_Renew"); DeclareFunctionUtil(curExternal, "eSystem_Renew"); break;
334             case renew0Exp:exp.call.exp = QMkExpId("ecere::com::eSystem_Renew0"); DeclareFunctionUtil(curExternal, "eSystem_Renew0"); break;
335          }
336          exp.call.arguments = args;
337          exp.type = callExp;
338
339          ProcessExpression(exp);
340          break;
341       }
342       case opExp:
343       {
344          Expression exp1 = exp.op.exp1;
345          Expression exp2 = exp.op.exp2;
346
347          switch(exp.op.op)
348          {
349             // Assignment Operators
350             case '=':
351                if(exp.op.exp2)
352                   exp.op.exp2.usage.usageGet = true;
353                break;
354             case MUL_ASSIGN:
355             case DIV_ASSIGN:
356             case MOD_ASSIGN:
357             case ADD_ASSIGN:
358             case SUB_ASSIGN:
359             case LEFT_ASSIGN:
360             case RIGHT_ASSIGN:
361             case AND_ASSIGN:
362             case XOR_ASSIGN:
363             case OR_ASSIGN:
364                exp.op.exp2.usage.usageGet = true;
365                break;
366
367             case INC_OP:
368             case DEC_OP:
369
370             // Unary operators
371             case '&':
372                // Also binary
373                if(exp.op.exp1 && exp.op.exp2)
374                {
375                   exp.op.exp1.usage.usageGet = true;
376                   exp.op.exp2.usage.usageGet = true;
377                }
378                else if(exp.op.exp2)
379                {
380                   exp.op.exp2.usage.usageRef = true;
381                }
382                break;
383             case '*':
384             case '+':
385             case '-':
386                // Also binary
387                if(exp.op.exp1)
388                {
389                   exp.op.exp1.usage.usageGet = true;
390                }
391             case '~':
392             case '!':
393                if(exp.op.exp2)
394                   exp.op.exp2.usage.usageGet = true;
395                break;
396
397             // Binary only operators
398             case '/':
399             case '%':
400             case LEFT_OP:
401             case RIGHT_OP:
402             case '<':
403             case '>':
404             case LE_OP:
405             case GE_OP:
406             case EQ_OP:
407             case NE_OP:
408             case '|':
409             case '^':
410             case AND_OP:
411             case OR_OP:
412                if(exp.op.exp1)
413                   exp.op.exp1.usage.usageGet = true;
414                if(exp.op.exp2)
415                   exp.op.exp2.usage.usageGet = true;
416                break;
417          }
418
419          if(exp.op.op == '=' || exp.op.op == MUL_ASSIGN || exp.op.op == DIV_ASSIGN || exp.op.op == ADD_ASSIGN ||
420             exp.op.op == MOD_ASSIGN || exp.op.op == SUB_ASSIGN || exp.op.op == LEFT_ASSIGN ||
421             exp.op.op == RIGHT_ASSIGN || exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN ||
422             exp.op.op == XOR_ASSIGN || exp.op.op == INC_OP || exp.op.op == DEC_OP)
423          {
424             Expression memberExp;
425             Expression parentExp = null; // Where to take memberExp out from
426             bool isIndexedContainerAssignment = false;
427
428             // TOCHECK: See note below for this if
429             if(exp.op.exp1 && exp.op.exp1.type == ExpressionType::memberExp)
430             {
431                // Extra bit of code to access deep properties...
432                Expression testExp, topExp = null;
433                Expression lastExp = exp.op.exp1, parentExp = null;
434                Property lastProperty = null;
435                Class propertyClass;
436
437                char setName[1024], getName[1024];
438                testExp = exp.op.exp1.member.exp;
439                while(true)
440                {
441                   // Is further fixing needed to address if statement above in the same way?
442                   while(testExp)
443                   {
444                      if(testExp.type == castExp)
445                         testExp = testExp.cast.exp;
446                      else if(testExp.type == bracketsExp || testExp.type == extensionExpressionExp)
447                         testExp = testExp.list->last;
448                      else if(testExp.type == ExpressionType::memberExp)
449                         break;
450                      else
451                         testExp = null;
452                   }
453                   if(!testExp) break;
454
455                   if(testExp.member.memberType == propertyMember ||
456                      testExp.member.memberType == reverseConversionMember)
457                   {
458                      Type type = testExp.member.exp.expType;
459                      if(type)
460                      {
461                         if(type.kind == classType)
462                         {
463                            Class _class = testExp.member.member.classSym ? testExp.member.member.classSym.registered : type._class.registered;
464                            Class convertTo = null;
465                            if(testExp.member.memberType == reverseConversionMember)
466                            {
467                               convertTo = _class;
468                               _class = FindClass(testExp.member.member.string).registered;
469                               // lastProperty = eClass_FindProperty(_class, convertTo.name, privateModule);
470                               lastProperty = eClass_FindProperty(_class, convertTo.fullName, privateModule);
471                            }
472                            else
473                            {
474                               lastProperty = eClass_FindProperty(_class, testExp.member.member.string, privateModule);
475                            }
476                            if(lastProperty && lastProperty.Get && lastProperty.Set)
477                            {
478                               DeclareProperty(curExternal, lastProperty, setName, getName);
479                               // propertyClass = convertTo ? _class : ((Symbol)lastProperty.symbol)._class;
480                               propertyClass = convertTo ? _class :
481                                  ((((Symbol)lastProperty.symbol).type &&
482                                     ((Symbol)lastProperty.symbol).type.kind == classType) ? ((Symbol)lastProperty.symbol).type._class.registered : ((Symbol)lastProperty.symbol)._class);
483                               // TODO: Handle this kind of things with bit classes?
484                               if(propertyClass && propertyClass.type == structClass)
485                               {
486                                  topExp = testExp;
487                                  parentExp = lastExp;
488                               }
489                               else if(propertyClass && propertyClass.type == bitClass)
490                               {
491                                  topExp = testExp;
492                                  parentExp = lastExp;
493                               }
494                            }
495
496                         }
497                      }
498                   }
499                   lastExp = testExp;
500
501                   testExp = testExp.member.exp;
502                }
503                if(topExp)
504                {
505                   if(propertyClass.type == structClass)
506                   {
507                      Expression copy;
508                      Expression value;
509                      char className[1024];
510                      Expression tempExp;
511
512                      sprintf(className, "__simpleStruct%d", curContext.simpleID); //++);
513                      tempExp = QMkExpId(className);
514                      tempExp.expType = MkClassType(propertyClass.fullName);
515
516                      parentExp.member.exp = tempExp;
517
518                      value = MkExpBrackets(MkList());
519
520                      copy = CopyExpression(topExp);
521                      copy.usage.usageGet = true;
522                      copy.usage.usageDeepGet = true;
523
524                      ListAdd(value.list, copy);
525                      ListAdd(value.list, MkExpOp(exp.op.exp1, exp.op.op, exp.op.exp2));
526                      ListAdd(value.list, CopyExpression(tempExp));
527                      value.expType = tempExp.expType;
528                      tempExp.expType.refCount++;
529
530                      // Go on as usual with these new values:
531                      exp.op.exp1 = topExp;
532                      exp.op.exp2 = value;
533                      exp.op.op = '=';
534
535                      exp1 = exp.op.exp1;
536                      exp2 = exp.op.exp2;
537                   }
538                   else if(propertyClass.type == bitClass)
539                   {
540                      Expression copy;
541                      Expression value;
542                      char className[1024];
543                      Expression tempExp;
544
545                      sprintf(className, "__simpleStruct%d", curContext.simpleID); //++);
546                      tempExp = QMkExpId(className);
547                      tempExp.expType = MkClassType(propertyClass.fullName);
548
549                      parentExp.member.exp = tempExp;
550
551                      value = MkExpBrackets(MkList());
552
553                      copy = CopyExpression(topExp);
554                      copy.usage.usageGet = true;
555                      copy.usage.usageDeepGet = true;
556
557                      ListAdd(value.list, copy);
558                      ListAdd(value.list, MkExpOp(exp.op.exp1, exp.op.op, exp.op.exp2));
559                      ListAdd(value.list, CopyExpression(tempExp));
560                      value.expType = tempExp.expType;
561                      value.expType.refCount++;
562
563                      //value = MkExpOp(exp.op.exp1, exp.op.op, exp.op.exp2);
564
565                      // Go on as usual with these new values:
566                      exp.op.exp1 = topExp;
567                      exp.op.exp2 = value;
568                      exp.op.op = '=';
569
570                      exp1 = exp.op.exp1;
571                      exp2 = exp.op.exp2;
572                   }
573                }
574             }
575
576             memberExp = exp.op.exp1;
577
578             while(memberExp && ((memberExp.type == bracketsExp && memberExp.list->count == 1) ||
579                memberExp.type == extensionExpressionExp || memberExp.type == extensionCompoundExp))
580             {
581                parentExp = memberExp;
582                if(memberExp.type == extensionCompoundExp)
583                   memberExp = ((Statement)memberExp.compound.compound.statements->last).expressions->last;
584                else
585                   memberExp = memberExp.list->last;
586             }
587
588             if(memberExp && memberExp.type == indexExp && memberExp.index.exp && memberExp.index.exp.expType &&
589                memberExp.index.exp.expType.kind == classType && memberExp.index.exp.expType._class && memberExp.index.exp.expType._class.registered &&
590                memberExp.index.exp.expType._class.registered != containerClass && eClass_IsDerived(memberExp.index.exp.expType._class.registered, containerClass))
591             {
592                Class c = memberExp.index.exp.expType._class.registered;
593                if(strcmp((c.templateClass ? c.templateClass : c).name, "Array"))
594                {
595                   exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), MkExpBrackets(MkListOne(exp.op.exp2)));
596                   exp.op.exp2 = MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), MkExpBrackets(MkListOne(exp.op.exp2)))));
597                   isIndexedContainerAssignment = true;
598                }
599
600                ProcessExpression(memberExp);
601
602                while(memberExp && ((memberExp.type == bracketsExp && memberExp.list->count == 1) ||
603                   memberExp.type == extensionExpressionExp || memberExp.type == extensionCompoundExp))
604                {
605                   parentExp = memberExp;
606                   if(memberExp.type == extensionCompoundExp)
607                      memberExp = ((Statement)memberExp.compound.compound.statements->last).expressions->last;
608                   else
609                      memberExp = memberExp.list->last;
610                }
611
612                if(memberExp && memberExp.type == extensionCompoundExp)
613                {
614                   parentExp = memberExp;
615                   if(memberExp.type == extensionCompoundExp)
616                   {
617                      Statement stmt = memberExp.compound.compound.statements ? memberExp.compound.compound.statements->last : null;
618                      if(stmt && stmt.type != expressionStmt) stmt = null;
619                      memberExp = (stmt && stmt.expressions) ? stmt.expressions->last : null;
620                      if(memberExp)
621                      {
622                         stmt.expressions->Remove(memberExp);
623                         stmt.expressions->Add(MkExpOp(memberExp, exp.op.op, exp.op.exp2));
624                         exp.type = bracketsExp;
625                         exp.list = MkListOne(parentExp);
626                         ProcessExpression(exp);
627                         break;
628                      }
629                   }
630                   else
631                      memberExp = memberExp.list->last;
632                }
633             }
634
635             if(memberExp && memberExp.type != ExpressionType::memberExp) memberExp = null;
636
637             if(memberExp && memberExp.type == ExpressionType::memberExp && memberExp.member.member)
638             {
639                Type type = memberExp.member.exp.expType;
640                if(type)
641                {
642                   // Check if it's an instance
643                   if(type.kind == classType || type.kind == subClassType)
644                   {
645                      // TODO: SOMETHING WRONG HERE...
646                      Class _class = memberExp.member.member.classSym ? (memberExp.member.member.classSym ? memberExp.member.member.classSym.registered : null) : (type._class ? type._class.registered : null);
647
648                      if(memberExp == exp1)
649                         exp1 = null;
650                      else
651                      {
652                         if(parentExp.type == extensionCompoundExp)
653                            ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(memberExp);
654                         else
655                            parentExp.list->Remove(memberExp);
656                      }
657
658                      if(_class && _class.type == bitClass && memberExp.member.memberType == dataMember)
659                      {
660                          BitMember bitMember =
661                             (BitMember)eClass_FindDataMember(_class,
662                               memberExp.member.member.string, privateModule, null, null);
663                          char mask[32], shift[10];
664                          OldList * specs = MkList();
665                          //Declarator decl = SpecDeclFromString(bitMember.dataTypeString, specs, null);
666                          Declarator decl = SpecDeclFromString(_class.dataTypeString, specs, null);
667                          TypeName type = MkTypeName(specs, decl);
668
669                          if(bitMember.mask > MAXDWORD)
670                             sprintf(mask, FORMAT64HEXLL, bitMember.mask);
671                          else
672                             sprintf(mask, FORMAT64HEX, bitMember.mask);
673                          sprintf(shift, "%d", bitMember.pos);
674
675                          // color = (color & ~0xFF0000) | (((unsigned char)200) << 16)
676                          exp.op.exp1 = memberExp.member.exp;
677
678                          // TESTING THIS FOR: argb.color.r = 1;
679                          //ProcessExpression(memberExp.member.exp);
680
681                          // TESTING THIS... FIX ELSEWHRE... FIX FOR OTHER OPS
682                          if(exp.op.op == XOR_ASSIGN)
683                          {
684                             exp.op.exp2 = MkExpOp(MkExpBrackets(
685                                  MkListOne(MkExpCast(type, exp.op.exp2))), LEFT_OP, MkExpConstant(shift));
686                          }
687                          else
688                          {
689                             exp.op.exp2 = MkExpOp(
690                                MkExpBrackets(MkListOne(MkExpOp(CopyExpression(memberExp.member.exp), '&',
691                                  MkExpOp(null, '~', MkExpConstant(mask))))), '|',
692                                MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(
693                                  MkListOne(MkExpCast(type, MkExpBrackets(MkListOne(exp.op.exp2))))), LEFT_OP, MkExpConstant(shift)))));
694                          }
695
696                          memberExp.member.exp = null;
697                          FreeExpression(memberExp);
698
699                          // TESTING THIS FOR: argb.color.r = 1;
700                          ProcessExpression(exp);
701                          return;
702                      }
703                      else if(_class && _class.type == unitClass && memberExp.member.memberType == dataMember)
704                      {
705                      }
706                      else if(memberExp.member.memberType != dataMember)
707                      {
708                         Property prop;
709                         Class convertTo = null;
710                         ClassProperty classProperty = null;
711
712                         if(memberExp.member.memberType == reverseConversionMember)
713                         {
714                            convertTo = _class;
715                            _class = FindClass(memberExp.member.member.string).registered;
716                            // prop = eClass_FindProperty(_class, convertTo.name, privateModule);
717                            prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
718                         }
719                         else
720                            prop = eClass_FindProperty(_class, memberExp.member.member.string, privateModule);
721
722                         if(memberExp.member.memberType == classPropertyMember)
723                            classProperty = eClass_FindClassProperty(_class, memberExp.member.member.string);
724
725                         exp.tempCount = memberExp.member.exp.tempCount;
726
727                         if(classProperty)
728                         {
729                            // Only process Gets here, Set is processed in opExp's '='
730                            if(classProperty.Set)
731                            {
732                               Identifier id = memberExp.member.member;
733                               Expression classExp = memberExp.member.exp;
734                               Expression value = exp.op.exp2;
735
736                               memberExp.member.exp = null;
737                               memberExp.member.member = null;
738                               exp.op.exp2 = null;
739
740                               FreeExpContents(memberExp);
741
742                               // Class Property
743                               exp.type = callExp;
744                               exp.call.exp = MkExpIdentifier(MkIdentifier("ecere::com::eClass_SetProperty"));
745                               exp.call.arguments = MkList();
746                               ListAdd(exp.call.arguments, classExp);
747                               {
748                                  char * s = QMkString(id.string);
749                                  ListAdd(exp.call.arguments, MkExpString(s));
750                                  delete s;
751                               }
752                               if(value.expType.isPointerType)
753                                  value = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("intptr")), null), value);
754                               ListAdd(exp.call.arguments, MkExpCast(MkTypeName(MkListOne(MkSpecifier(INT64)), null), value));
755
756                               FreeIdentifier(id);
757
758                               ProcessExpression(exp);
759                               return;
760                            }
761                         }
762                         else if(prop)
763                         {
764                            if((!convertTo && prop.Set) || (convertTo && prop.Get))
765                            {
766                               Expression value = exp.op.exp2;
767                               char setName[1024], getName[1024];
768                               char * setToUse = convertTo ? getName : setName;
769                               char * getToUse = convertTo ? setName : getName;
770                               bool needAddress = false;
771                               int operator = exp.op.op;
772                               switch(operator)
773                               {
774                                  case MUL_ASSIGN: operator = '*'; break;
775                                  case DIV_ASSIGN: operator = '/'; break;
776                                  case MOD_ASSIGN: operator = '%'; break;
777                                  case SUB_ASSIGN: operator = '-'; break;
778                                  case ADD_ASSIGN: operator = '+'; break;
779                                  case LEFT_ASSIGN: operator = LEFT_OP; break;
780                                  case RIGHT_ASSIGN: operator = RIGHT_OP; break;
781                                  case AND_ASSIGN: operator = '&'; break;
782                                  case OR_ASSIGN: operator = '|'; break;
783                                  case XOR_ASSIGN: operator = '^'; break;
784                               }
785
786                               if(operator != '=')
787                               {
788                                  if(operator == INC_OP)
789                                     value = MkExpOp(CopyExpression(memberExp),
790                                        '+', MkExpConstant("1"));
791                                  else if(operator == DEC_OP)
792                                     value = MkExpOp(CopyExpression(memberExp),
793                                        '-', MkExpConstant("1"));
794                                  else
795                                  {
796                                     value = MkExpOp(CopyExpression(memberExp),
797                                        operator, value);
798                                     exp2 = null;
799                                  }
800                                  value.expType = memberExp.expType;
801                                  memberExp.expType.refCount++;
802                                  value.usage.usageArg = true;
803                               }
804                               else if(value)
805                               {
806                                  // Dont free exp2, we're using it
807                                  exp2 = null;
808                               }
809
810                               if(value)
811                                  value.usage.usageArg = true;
812
813                               DeclareProperty(curExternal, prop, setName, getName);
814
815                               if(memberExp.member.exp)
816                                  ProcessExpression(memberExp.member.exp);
817
818                               // If get flag present
819                               if(exp.usage.usageGet &&
820                                  ((!convertTo && prop.Get) || (convertTo && prop.Set)))
821                               {
822                                  OldList * list = MkList();
823                                  OldList * args;
824                                  char ecereTemp[100];
825                                  Context context = PushContext();
826                                  exp.tempCount++;
827
828                                  curExternal.function.tempCount = Max(curExternal.function.tempCount, exp.tempCount);
829                                  sprintf(ecereTemp, "__ecTemp%d", exp.tempCount);
830
831                                  curContext = context;
832                                  exp.type = extensionCompoundExp;
833                                  exp.compound = MkCompoundStmt(
834                                     MkListOne(MkDeclaration(MkListOne(MkSpecifier(VOID)), MkListOne(MkInitDeclarator(
835                                        MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier(ecereTemp))),
836                                           MkInitializerAssignment(QBrackets(memberExp.member.exp)))))),
837                                     list);
838
839                                  // Add the set
840                                  args = MkList();
841                                  if(convertTo)
842                                  {
843                                     ListAdd(args, value);
844                                     ListAdd(args, QMkExpId(ecereTemp));
845                                     ListAdd(list, MkExpressionStmt(MkListOne(MkExpCall(QMkExpId(getName), args))));
846                                  }
847                                  else
848                                  {
849                                     ListAdd(args, QMkExpId(ecereTemp));
850                                     ListAdd(args, value);
851                                     ListAdd(list, MkExpressionStmt(MkListOne(MkExpCall(QMkExpId(setName), args))));
852                                  }
853
854                                  // Add the get
855                                  args = MkList();
856                                  if(convertTo)
857                                     ListAdd(args, QMkExpId(ecereTemp));
858                                  else
859                                     args->Insert(null, QMkExpId(ecereTemp));
860                                  ListAdd(list, MkExpressionStmt(MkListOne(MkExpCall(QMkExpId(getToUse), args))));
861
862                                  exp.compound.compound.context = context;
863                                  PopContext(context);
864                                  curContext = context.parent;
865                               }
866                               else
867                               {
868                                  Expression newExp = exp;
869
870                                  if(parentExp && parentExp.type == extensionCompoundExp)
871                                  {
872                                     newExp = Expression { };
873                                     ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
874                                     FreeType(exp.expType);
875                                     FreeType(exp.destType);
876                                     exp = *parentExp;
877                                     //delete parentExp;
878                                     parentExp.type = dummyExp;
879                                     parentExp.expType = null;
880                                     parentExp.destType = null;
881                                  }
882
883                                  newExp.type = callExp;
884                                  newExp.call.exp = QMkExpId(setToUse);
885                                  newExp.call.arguments = MkList();
886                                  if(convertTo)
887                                  {
888                                     ListAdd(newExp.call.arguments, value);
889                                     ListAdd(newExp.call.arguments, FixReference(memberExp.member.exp, true));
890                                  }
891                                  else
892                                  {
893                                     ListAdd(newExp.call.arguments, FixReference(memberExp.member.exp, true));
894                                     ListAdd(newExp.call.arguments, value);
895                                  }
896                                  needAddress = true;
897                               }
898
899                               // Take it out from there
900                               memberExp.member.exp = null;
901
902                               // Don't use the temporaries used by the left side...
903                               if(value)
904                               {
905                                  value.tempCount = exp.tempCount;
906                                  ProcessExpression(value);
907                                  if(needAddress)
908                                     FixReference(isIndexedContainerAssignment ? GetInnerExp(value) : value, true);
909                               }
910
911                               FreeExpression(memberExp);
912                            }
913                            else
914                            {
915                               DataMember member = eClass_FindDataMember(_class, memberExp.member.member.string, privateModule, null, null);
916                               if(member)
917                               {
918                                  memberExp.member.memberType = dataMember;
919                               }
920                               else
921                                  Compiler_Error($"no set defined for property %s of class %s\n", prop.name, prop._class.fullName);
922                            }
923                         }
924                         else
925                         {
926                            Method method = eClass_FindMethod(_class, memberExp.member.member.string, privateModule);
927                            if(method && method.type == virtualMethod && type.kind != subClassType)
928                            {
929                               Expression value = exp.op.exp2;
930                               // Don't use the temporaries used by the left side...
931                               value.tempCount = exp.tempCount;
932                               ProcessExpression(value);
933
934                               if(memberExp.member.exp)
935                                  ProcessExpression(memberExp.member.exp);
936
937                               if(exp.usage.usageGet)
938                               {
939                                  OldList * list = MkList();
940                                  OldList * args;
941
942                                  // Set the method
943                                  args = MkList();
944                                  ListAdd(args, memberExp.member.exp);
945                                  {
946                                     char * string = QMkString(memberExp.member.member.string);
947                                     ListAdd(args, MkExpString(string));
948                                     delete string;
949                                  }
950                                  ListAdd(args, value);
951                                  ListAdd(list, MkExpCall(QMkExpId("ecere::com::eInstance_SetMethod"), args));
952                                  ListAdd(list, CopyExpression(value));
953                                  exp.type = bracketsExp;
954                                  exp.list = list;
955                               }
956                               else
957                               {
958                                  // Set the method
959                                  exp.type = callExp;
960                                  exp.call.exp = QMkExpId("ecere::com::eInstance_SetMethod");
961                                  exp.call.arguments = MkList();
962                                  ListAdd(exp.call.arguments, memberExp.member.exp);
963                                  {
964                                     char * string = QMkString(memberExp.member.member.string);
965                                     ListAdd(exp.call.arguments, MkExpString(string));
966                                     delete string;
967                                  }
968                                  ListAdd(exp.call.arguments, value);
969                               }
970
971                               memberExp.member.exp = null;
972                               exp2 = null;
973
974                               FreeExpression(memberExp);
975                            }
976                         }
977                      }
978                      else if(memberExp.member.memberType == dataMember)
979                      {
980                         //if(exp.usage & USAGE_GET);
981                         //FixReference(value, true);
982                         if(FixMember(memberExp.member.exp))
983                         {
984                            // TESTING THIS HERE:
985                            ProcessExpression(memberExp);
986
987                            memberExp.type = pointerExp;
988                         }
989                      }
990                   }
991                }
992             }
993          }
994          else if(exp.op.op == _INCREF)
995          {
996             Expression object = exp.op.exp2;
997             exp.op.exp2 = null;
998             FreeExpContents(exp);
999             FreeType(exp.expType);
1000             FreeType(exp.destType);
1001             exp.expType = null;
1002             exp.destType = null;
1003             exp.op.op = INC_OP;
1004             exp.op.exp1 = MkExpPointer(object, MkIdentifier("_refCount"));
1005          }
1006          else if(exp.op.op == DELETE)
1007          {
1008             Expression object = exp.op.exp2;
1009             OldList * args = MkList();
1010
1011             exp.type = bracketsExp;
1012             exp.list = MkList();
1013
1014             object.usage.usageDelete = true;
1015
1016             ProcessExpression(object);
1017
1018             ListAdd(args, object);
1019
1020             // TOFIX: Same time as when we fix for = 0
1021
1022             if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
1023                exp.expType._class.registered.type == normalClass &&
1024                strcmp(exp.expType._class.registered.dataTypeString, "char *"))
1025             {
1026                Expression decRefExp = MkExpCall(QMkExpId("ecere::com::eInstance_DecRef"), args);
1027                ProcessExpressionType(decRefExp);
1028                ListAdd(exp.list, decRefExp);
1029             }
1030             else if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == noHeadClass)
1031             {
1032                /*
1033                char className[1024];
1034                OldList * list = MkList();
1035
1036                strcpy(className, "__ecereClass_");
1037                FullClassNameCat(className, exp.expType._class.string, true);
1038
1039                DeclareClass(exp.expType._class, className);
1040
1041                // Call the non virtual destructor
1042                ListAdd(list, MkExpCall(MkExpPointer(QMkExpId(className), MkIdentifier("Destructor")), CopyList(args, CopyExpression)));
1043                ListAdd(list, MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), args));
1044
1045                ListAdd(exp.list, MkExpBrackets(MkListOne(MkExpCondition(CopyExpression(object), MkListOne(
1046
1047                   MkExpBrackets(MkListOne(MkExpCondition(
1048                   MkExpPointer(QMkExpId(className), MkIdentifier("Destructor")),
1049                   MkListOne(MkExpBrackets(list)), MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), CopyList(args, CopyExpression)))))), MkExpConstant("0"))))
1050
1051                   );
1052                */
1053
1054                OldList * list = MkList();
1055                Class _class;
1056                Statement stmt;
1057                Expression o;
1058                Statement compound = MkCompoundStmt(MkListOne(MkDeclaration(MkListOne(MkSpecifier(VOID)), MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__ecerePtrToDelete"))),
1059                   MkInitializerAssignment(MkExpBrackets(args)))))), MkListOne(stmt = MkExpressionStmt(list)));
1060                Expression stmtExp = MkExpExtensionCompound(compound);
1061                for(_class = exp.expType._class.registered; _class && _class.type == noHeadClass; _class = _class.base)
1062                {
1063                   char className[1024];
1064
1065                   if(_class.templateClass) _class = _class.templateClass;
1066                   strcpy(className, "__ecereClass_");
1067                   FullClassNameCat(className, _class.fullName, false /*true*/);
1068
1069                   if(!_class.symbol)
1070                      _class.symbol = FindClass(_class.fullName);
1071                   DeclareClass(curExternal, _class.symbol, className);
1072
1073                   // Call the non virtual destructor
1074                   ListAdd(list,
1075                      MkExpCondition(
1076                         MkExpPointer(
1077                            QMkExpId(className),
1078                            MkIdentifier("Destructor")
1079                         ),
1080                         MkListOne(
1081                            MkExpCall(
1082                               MkExpPointer(
1083                                  QMkExpId(className),
1084                                  MkIdentifier("Destructor")
1085                               ),
1086                               MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null)), MkExpIdentifier(MkIdentifier("__ecerePtrToDelete")) /*CopyExpression(args->first)*/))
1087                            )
1088                         ),
1089                         MkExpConstant("0")
1090                      )
1091                   );
1092                }
1093                ListAdd(list, MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), MkListOne(MkExpIdentifier(MkIdentifier("__ecerePtrToDelete"))) /*args*/));
1094                DeclareFunctionUtil(curExternal, "eSystem_Delete");
1095                o = CopyExpression(object);
1096                ProcessExpressionType(o);
1097                o.usage.usageGet = true;
1098                ProcessExpression(o);
1099
1100                ListAdd(exp.list,
1101                   MkExpBrackets(
1102                      MkListOne(
1103                         MkExpCondition(
1104                            o,
1105                            MkListOne(
1106                               //MkExpBrackets(list)
1107                               stmtExp
1108                            ),
1109                            MkExpConstant("0")
1110                         )
1111                      )
1112                   )
1113                );
1114             }
1115             else if(exp.expType && exp.expType.kind == templateType)
1116             {
1117                Expression argExp = GetTemplateArgExp(exp.expType.templateParameter, thisClass, false);
1118                if(argExp)
1119                {
1120                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1121                   TypeName typeName;
1122                   OldList * qualifiers = MkList();
1123                   Declarator declarator = SpecDeclFromString("void (*)(void * _class, void * data)", qualifiers, null);
1124
1125                   typeName = MkTypeName(qualifiers, declarator);
1126
1127                   ProcessExpressionType(classExp);
1128                   ProcessExpression(classExp);
1129                   args->Insert(null, CopyExpression(classExp));
1130                   DeclareMethod(curExternal, eClass_FindMethod(eSystem_FindClass(privateModule, "class"), "OnFree", privateModule), "__ecereVMethodID_class_OnFree");
1131                   ListAdd(exp.list, MkExpCall(
1132                      MkExpBrackets(MkListOne(MkExpCast(typeName,
1133                         MkExpIndex(MkExpPointer(classExp, MkIdentifier("_vTbl")),
1134                            MkListOne(MkExpIdentifier(MkIdentifier("__ecereVMethodID_class_OnFree"))))))), args));
1135                   //ProcessExpression(exp.list->last);
1136                }
1137             }
1138             else
1139             {
1140                ListAdd(exp.list, MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), args));
1141                DeclareFunctionUtil(curExternal, "eSystem_Delete");
1142             }
1143
1144             //ProcessExpression(object);
1145
1146             ListAdd(exp.list, MkExpOp(CopyExpression(GetInnerExp(object)), '=', MkExpConstant("0")));
1147
1148             exp2 = null;
1149
1150             // TESTING THIS HERE...
1151             ProcessExpression(exp);
1152          }
1153
1154          if(exp.type == opExp)
1155          {
1156             // Handle assigment of template structures
1157             if(exp.op.op == '=' && exp.op.exp1 && exp.op.exp1.expType && exp.op.exp1.expType.kind == templateType &&
1158                (exp.op.exp1.type == indexExp || (exp.op.exp1.type == opExp && exp.op.exp1.op.op == '*' && !exp.op.exp1.op.exp1)))
1159             {
1160                Expression argExp = GetTemplateArgExp(exp.op.exp1.expType.templateParameter, thisClass, false);
1161                if(argExp)
1162                {
1163                   // memcpy((byte *)array + (count * dataTypeClass.size), (dataTypeClass.type == structClass) ? value : &value, dataTypeClass.size);
1164
1165                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1166                   OldList * args = MkList();
1167                   Expression derefExp = exp.op.exp1;
1168                   Expression sizeExp;
1169
1170                   ProcessExpressionType(classExp);
1171                   ProcessExpression(classExp);
1172
1173                   sizeExp = MkExpMember(CopyExpression(classExp), MkIdentifier("typeSize"));
1174
1175                   if(exp.op.exp1.type == indexExp)
1176                   {
1177                      Expression indexExp = derefExp.index.exp;
1178                      OldList * indexExpIndex = derefExp.index.index;
1179
1180                      derefExp.index.index = null;
1181                      derefExp.index.exp = null;
1182                      FreeExpression(derefExp);
1183
1184                      // BOOSTRAP FIX
1185                      derefExp = MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)), indexExp), '+',
1186                         MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(indexExpIndex), '*', MkExpBrackets(MkListOne(CopyExpression(sizeExp)))))));
1187                   }
1188                   else
1189                   {
1190                      Expression indexExp = derefExp.op.exp2;
1191                      derefExp.op.exp2 = null;
1192                      FreeExpression(derefExp);
1193                      derefExp = indexExp;
1194                   }
1195
1196                   args->Add(derefExp);
1197                   ProcessExpressionType(args->last);
1198                   ProcessExpression(args->last);
1199
1200                   args->Add(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)),
1201                      MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(MkExpMember(classExp, MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("structClass"))))),
1202                            MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), MkExpBrackets(MkListOne(exp.op.exp2))))),
1203                            MkExpOp(null, '&', CopyExpression(exp.op.exp2)))));
1204
1205                   thisClass = curExternal.function ? curExternal.function._class : null;
1206                   {
1207                      Symbol thisSymbol
1208                      {
1209                         string = CopyString("this");
1210                         type = MkClassType(thisClass.fullName);
1211                      };
1212                      globalContext.symbols.Add((BTNode)thisSymbol);
1213
1214                      ProcessExpressionType(args->last);
1215                      ProcessExpression(args->last);
1216
1217                      args->Add(sizeExp);
1218                      ProcessExpressionType(args->last);
1219                      ProcessExpression(args->last);
1220
1221                      DeclareFunctionUtil(curExternal, "memcpy");
1222
1223                      exp.list = MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("memcpy")), args));
1224                      exp.type = bracketsExp;
1225
1226                      //globalContext.symbols.Delete((BTNode)thisSymbol);
1227                      globalContext.symbols.Remove((BTNode)thisSymbol);
1228                      FreeSymbol(thisSymbol);
1229                   }
1230                   thisClass = null;
1231                   return;
1232                }
1233             }
1234             else if(exp.op.op == '*' && !exp.op.exp1 && exp.op.exp2 && exp.op.exp2.expType && exp.op.exp2.expType.kind == pointerType &&
1235                exp.op.exp2.expType.type && exp.op.exp2.expType.type.kind == templateType)
1236             {
1237                Expression argExp = GetTemplateArgExp(exp.op.exp2.expType.type.templateParameter, thisClass, false);
1238                if(argExp)
1239                {
1240                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1241                   Expression sizeExp;
1242
1243                   ProcessExpressionType(classExp);
1244                   ProcessExpression(classExp);
1245
1246                   sizeExp = MkExpMember(CopyExpression(classExp), MkIdentifier("typeSize"));
1247
1248                   exp.type = bracketsExp;
1249                   exp.list = MkListOne(
1250                      // (uint64)
1251                      MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null),
1252
1253                      // ((class.type == structClass) ?
1254                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("structClass"))))),
1255                         // array
1256                         MkListOne(
1257                            MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), CopyExpression(exp.op.exp2)))))),
1258
1259                      // ((class.size == 1) ?
1260                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("1")))),
1261                         // *((byte *)array)
1262                         MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
1263                            CopyExpression(exp.op.exp2)))))),
1264
1265                      // ((class.size == 2) ?
1266                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("2")))),
1267                         // *((uint16 *)array)
1268                         MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint16")), MkDeclaratorPointer(MkPointer(null, null), null)),
1269                            CopyExpression(exp.op.exp2)))))),
1270
1271                      // ((class.size == 4) ?
1272                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(sizeExp, EQ_OP, MkExpConstant("4")))),
1273                         // *((uint32 *)array)
1274                         MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint32")), MkDeclaratorPointer(MkPointer(null, null), null)),
1275                            CopyExpression(exp.op.exp2)))))),
1276
1277                      // *((uint64 *)array)
1278                      MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
1279                         exp.op.exp2))))))))))))))))))));
1280
1281                   // Add this to the context
1282                   thisClass = curExternal.function ? curExternal.function._class : null;
1283                   {
1284                      Symbol thisSymbol
1285                      {
1286                         string = CopyString("this");
1287                         type = MkClassType(thisClass.fullName);
1288                      };
1289                      globalContext.symbols.Add((BTNode)thisSymbol);
1290
1291                      ProcessExpressionType(exp.list->first);
1292                      ProcessExpression(exp.list->first);
1293
1294                      //globalContext.symbols.Delete((BTNode)thisSymbol);
1295                      globalContext.symbols.Remove((BTNode)thisSymbol);
1296                      FreeSymbol(thisSymbol);
1297                   }
1298                   thisClass = null;
1299                   return;
1300                }
1301             }
1302             else
1303             {
1304                if(exp.op.exp1)
1305                {
1306                   if(exp.op.exp2)
1307                      // TEST: exp.op.exp1.tempCount = Max(exp.op.exp1.tempCount, exp.op.exp2.tempCount);
1308                      exp.op.exp1.tempCount = exp.op.exp2.tempCount;
1309                   ProcessExpression(exp.op.exp1);
1310
1311                   // TESTING THIS...
1312                   if(exp.op.op == '=' && exp.op.exp2 && (!exp.op.exp2.byReference ||
1313                      (exp.op.exp2.expType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class &&
1314                       exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass)) &&
1315                      exp.op.exp2.expType && (exp.op.exp2.expType.kind != pointerType && exp.op.exp2.expType.kind != templateType /*|| !exp.op.exp2.expType.type || exp.op.exp2.expType.type.kind != voidType*/))
1316                      FixReference(exp.op.exp1, false);
1317                   // TEST: exp.tempCount = Max(exp.op.exp1.tempCount, exp.tempCount);
1318                }
1319                if(exp.op.exp2)
1320                {
1321                   // Don't use the temporaries used by the left side...
1322                   if(exp.op.exp1)
1323                      // TEST: exp.op.exp2.tempCount = Max(exp.op.exp2.tempCount, exp.op.exp1.tempCount);
1324                      exp.op.exp2.tempCount = exp.op.exp1.tempCount;
1325                   ProcessExpression(exp.op.exp2);
1326                   if(exp.op.exp1 || (exp.op.op != '*' && exp.op.op != '&'))
1327                   {
1328                      // TESTING THIS IF:
1329                      if((!exp.op.exp1 &&
1330                         (!exp.op.exp2 || !exp.op.exp2.expType || exp.op.exp2.expType.kind != classType || !exp.op.exp2.expType._class || !exp.op.exp2.expType._class.registered ||
1331                         (exp.op.exp2.expType._class.registered.type != normalClass &&
1332                          exp.op.exp2.expType._class.registered.type != structClass &&
1333                          exp.op.exp2.expType._class.registered.type != noHeadClass)))
1334
1335                             // TESTING THIS TEMPLATE TYPE CHECK HERE
1336                         || (exp.op.exp1 && exp.op.exp1.expType && exp.op.exp1.expType.kind != pointerType && exp.op.exp1.expType.kind != templateType))
1337                      {
1338                         FixReference(exp.op.exp2, exp.op.exp1 ? exp.op.exp1.byReference : false);
1339                         //FixReference(exp.op.exp2, false);
1340                      }
1341                   }
1342                   // TEST: exp.tempCount = Max(exp.op.exp2.tempCount, exp.tempCount);
1343                }
1344             }
1345             if(exp.op.op == '*' && !exp.op.exp1 && exp.op.exp2 && exp.op.exp2.type == opExp && exp.op.exp2.op.op == '&' && !exp.op.exp2.op.exp1)
1346             {
1347                // Preserve prev, next
1348                Expression next = exp.next, prev = exp.prev;
1349                Expression derefExp = exp.op.exp2;
1350                Expression refExp = exp.op.exp2.op.exp2;
1351
1352                derefExp.op.exp2 = null;
1353                FreeExpression(derefExp);
1354                FreeType(exp.expType);
1355                FreeType(exp.destType);
1356
1357                *exp = refExp;
1358
1359                exp.prev = prev;
1360                exp.next = next;
1361
1362                delete refExp;
1363             }
1364
1365             if(exp.op.op == '&' && !exp.op.exp1 && exp.op.exp2 && exp.op.exp2.expType && exp.op.exp2.expType.kind == templateType && !exp.op.exp2.expType.passAsTemplate)
1366             {
1367                Expression exp2 = exp.op.exp2;
1368                Expression argExp = GetTemplateArgExp(exp2.expType.templateParameter, thisClass, false);
1369                if(argExp)
1370                {
1371                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1372                   Expression e;
1373
1374                   ProcessExpressionType(classExp);
1375                   ProcessExpression(classExp);
1376
1377                   exp.type = bracketsExp;
1378                   exp.list = MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)),
1379                                  MkExpOp(null, '&', exp2)), '+',
1380                                     MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")),
1381                                        MkListOne((e = MkExpMember(classExp, MkIdentifier("typeSize")))))));
1382
1383                                              // Add this to the context
1384                   thisClass = curExternal.function ? curExternal.function._class : null;
1385                   {
1386                      /*Symbol thisSymbol
1387                      {
1388                         string = CopyString("this");
1389                         type = MkClassType(thisClass.fullName);
1390                      };*/
1391                      //globalContext.symbols.Add((BTNode)thisSymbol);
1392
1393                      ProcessExpressionType(e);
1394                      ProcessExpression(e);
1395
1396                      //globalContext.symbols.Remove((BTNode)thisSymbol);
1397                      //FreeSymbol(thisSymbol);
1398                   }
1399                   thisClass = null;
1400                }
1401             }
1402          }
1403          else
1404          {
1405             if(exp1)
1406                FreeExpression(exp1);
1407             if(exp2)
1408                FreeExpression(exp2);
1409          }
1410          break;
1411       }
1412       case bracketsExp:
1413       case extensionExpressionExp:
1414       {
1415          if(exp.list)
1416          {
1417             Expression e;
1418             for(e = exp.list->first; e; e = e.next)
1419             {
1420                if(!e.next)
1421                {
1422                   e.usage |= (exp.usage & ExpUsage { usageGet = true, usageArg = true, usageMember = true });
1423                }
1424                e.tempCount = exp.tempCount;
1425                ProcessExpression(e);
1426                if(!e.next)
1427                   exp.byReference = e.byReference;
1428                exp.tempCount = e.tempCount;
1429
1430                /*
1431                if(!e.next)
1432                   exp.expType = e.expType;
1433                */
1434             }
1435          }
1436          break;
1437       }
1438       case indexExp:
1439       {
1440          Expression e;
1441          /*bool isBuiltin = exp && exp.index.exp &&
1442             (exp.index.exp.type == ExpressionType::arrayExp ||
1443               (exp.index.exp.type == castExp && exp.index.exp.cast.exp.type == ExpressionType::arrayExp));
1444          */
1445          Expression checkedExp = exp.index.exp;
1446          bool isBuiltin = false;
1447
1448          while(checkedExp.type == extensionCompoundExp || checkedExp.type == bracketsExp || checkedExp.type == castExp)
1449          {
1450             if(checkedExp.type == extensionCompoundExp)
1451             {
1452                isBuiltin = true;
1453                break;
1454             }
1455             else if(checkedExp.type == bracketsExp)
1456                checkedExp = checkedExp.list ? checkedExp.list->last : null;
1457             else
1458                checkedExp = checkedExp.cast.exp;
1459          }
1460
1461          exp.index.exp.tempCount = exp.tempCount;
1462
1463          exp.index.exp.usage.usageGet = true;
1464          ProcessExpression(exp.index.exp);
1465
1466          if(exp.index.exp.expType && exp.index.exp.expType.kind == pointerType &&
1467             exp.index.exp.expType.type && exp.index.exp.expType.type.kind == templateType)
1468          {
1469             Expression argExp = GetTemplateArgExp(exp.index.exp.expType.type.templateParameter, thisClass, false);
1470             if(argExp)
1471             {
1472                Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1473                Expression sizeExp;
1474
1475                ProcessExpressionType(classExp);
1476                ProcessExpression(classExp);
1477
1478                sizeExp = MkExpMember(CopyExpression(classExp), MkIdentifier("typeSize"));
1479
1480                exp.type = bracketsExp;
1481                exp.list = MkListOne(
1482                   // (uint64)
1483                   MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null),
1484
1485                   // ((class.type == structClass) ?
1486                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("structClass"))))),
1487                      // ((byte *)array) + (i) * class.size
1488                      MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), MkExpBrackets(MkListOne(MkExpOp(
1489                         MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), CopyExpression(exp.index.exp)))), '+',
1490                         MkExpOp(MkExpBrackets(CopyList(exp.index.index, CopyExpression)), '*', CopyExpression(sizeExp)))))))),
1491
1492                   // ((class.size == 1) ?
1493                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("1")))),
1494                      // ((byte *)array)[i]
1495                      MkListOne(MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
1496                         CopyExpression(exp.index.exp)))), CopyList(exp.index.index, CopyExpression))),
1497
1498                   // ((class.size == 2) ?
1499                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("2")))),
1500                      // ((uint16 *)array)[i]
1501                      MkListOne(MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint16")), MkDeclaratorPointer(MkPointer(null, null), null)),
1502                         CopyExpression(exp.index.exp)))), CopyList(exp.index.index, CopyExpression))),
1503
1504                   // ((class.size == 4) ?
1505                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(sizeExp, EQ_OP, MkExpConstant("4")))),
1506                      // ((uint32 *)array)[i]
1507                      MkListOne(MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint32")), MkDeclaratorPointer(MkPointer(null, null), null)),
1508                         CopyExpression(exp.index.exp)))), CopyList(exp.index.index, CopyExpression))),
1509
1510                   // ((uint64 *)array)[i]
1511                   MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
1512                      exp.index.exp))), exp.index.index)))))))))))))))));
1513
1514                // Add this to the context
1515                thisClass = curExternal.function ? curExternal.function._class : null;
1516                {
1517                   Symbol thisSymbol
1518                   {
1519                      string = CopyString("this");
1520                      type = MkClassType(thisClass.fullName);
1521                   };
1522                   globalContext.symbols.Add((BTNode)thisSymbol);
1523
1524                   ProcessExpressionType(exp.list->first);
1525                   ProcessExpression(exp.list->first);
1526
1527                   //globalContext.symbols.Delete((BTNode)thisSymbol);
1528                   globalContext.symbols.Remove((BTNode)thisSymbol);
1529                   FreeSymbol(thisSymbol);
1530                }
1531                thisClass = null;
1532
1533                return;
1534             }
1535          }
1536
1537          for(e = exp.index.index->first; e; e = e.next)
1538          {
1539             if(!e.next)
1540                e.usage.usageGet = true;
1541             ProcessExpression(e);
1542          }
1543          // Ignore temps in the index for now...
1544          exp.tempCount = exp.index.exp.tempCount;
1545
1546          if(exp.index.exp.expType)
1547          {
1548             Type source = exp.index.exp.expType;
1549             if(/*isBuiltin || */source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
1550                eClass_IsDerived(source._class.registered, containerClass))
1551             {
1552                Class _class = source._class.registered;
1553                bool isArray = false;
1554                Class arrayClass = eSystem_FindClass(privateModule, "Array");
1555                if(source && eClass_IsDerived(source._class.registered, arrayClass))
1556                   isArray = true;
1557                if(isArray && _class.templateArgs)
1558                {
1559                   OldList * specs = MkList();
1560                   Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, null);
1561                   TypeName typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
1562                   exp.index.exp = MkExpBrackets(MkListOne(MkExpCast(typeName, MkExpMember(exp.index.exp, MkIdentifier("array")))));
1563                   ProcessExpressionType(exp.index.exp);
1564                   ProcessExpression(exp);
1565                }
1566                else if(isBuiltin && _class.templateArgs)
1567                {
1568                   OldList * specs = MkList();
1569                   Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, null);
1570                   TypeName typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
1571                   exp.index.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1572                      MkExpPointer(MkExpCast(QMkType("BuiltInContainer", QMkPtrDecl(null)), exp.index.exp), MkIdentifier("data")))));
1573                   ProcessExpressionType(exp.index.exp);
1574                   ProcessExpression(exp);
1575                }
1576                else if(_class.templateArgs)
1577                {
1578                   // __extension__({ Iterator<type> i { container }; i.Index(e, [ exp.usage.usageSet ]; i.value; });
1579
1580                   char iteratorType[1024];
1581                   OldList * declarations = MkList();
1582                   OldList * statements = MkList();
1583                   OldList * args = MkList();
1584                   OldList * instMembers = MkList();
1585                   Expression expExt;
1586                   Context context = PushContext();
1587
1588                   sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
1589
1590                   ListAdd(instMembers, MkMemberInit(null, MkInitializerAssignment(exp.index.exp)));
1591
1592                   ListAdd(declarations, MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
1593                      MkExpIdentifier(MkIdentifier("__internalIterator")), MkListOne(MkMembersInitList(instMembers)))));
1594
1595                   ListAdd(args, MkExpBrackets(exp.index.index));
1596                   ListAdd(args, exp.usage.usageSet ? MkExpIdentifier(MkIdentifier("true")) : MkExpIdentifier(MkIdentifier("false")));
1597
1598                   ListAdd(statements, MkExpressionStmt(MkListOne(MkExpCall(MkExpMember(MkExpIdentifier(MkIdentifier("__internalIterator")),
1599                      MkIdentifier("Index")), args))));
1600
1601                   // ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(null, '&', MkExpIdentifier(MkIdentifier("__internalIterator"))))));
1602                   ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internalIterator")), MkIdentifier("data")))));
1603
1604                   exp.type = bracketsExp;
1605                   // exp.list = MkListOne(MkExpPointer(expExt = (MkExpExtensionCompound(MkCompoundStmt(declarations, statements))), MkIdentifier("data")));
1606                   exp.list = MkListOne(expExt = (MkExpExtensionCompound(MkCompoundStmt(declarations, statements))));
1607                   expExt.compound.compound.context = context;
1608                   PopContext(context);
1609                   expExt.usage = exp.usage;
1610                   ProcessExpressionType(exp.list->first);
1611                   ProcessExpressionInstPass(exp.list->first);
1612                   ProcessExpression(exp.list->first);
1613                }
1614             }
1615          }
1616          break;
1617       }
1618       case callExp:
1619       {
1620          Expression e;
1621          bool typedObject = false;
1622          Type ellipsisDestType = null;
1623          bool usedEllipsis = false;
1624          Expression expCallExp = exp.call.exp;
1625          OldList * arguments = exp.call.arguments;
1626          bool handleNullVMethod = false;
1627          TypeName typeName = null;
1628
1629          if(arguments)
1630          {
1631             for(e = arguments->first; e; e = e.next)
1632             {
1633                e.usage.usageGet = true;
1634                e.usage.usageArg = true;
1635                e.tempCount = Max(e.tempCount, exp.tempCount);
1636                ProcessExpression(e);
1637                exp.tempCount = Max(exp.tempCount, e.tempCount);
1638             }
1639          }
1640          expCallExp.usage.usageGet = true;
1641          expCallExp.usage.usageCall = true;
1642          expCallExp.tempCount = exp.tempCount;
1643
1644          ProcessExpression(expCallExp);
1645
1646          if(expCallExp.expType && expCallExp.expType.kind == methodType)
1647          {
1648             bool nullMemberExp = false;
1649             Expression memberExp = (expCallExp.type == ExpressionType::memberExp) ? expCallExp : null;
1650
1651             Class _class = expCallExp.expType.methodClass;     // For Virtual Method
1652             Class argClass = expCallExp.expType.methodClass;  // Class actually passed
1653             Method method = expCallExp.expType.method;
1654             if(method.type == virtualMethod)
1655             {
1656                char name[1024];
1657                Declarator decl;
1658                Context back;
1659                OldList * specs = MkList();
1660                strcpy(name, "__ecereVMethodID_");
1661                FullClassNameCat(name, method._class.fullName, false);
1662                strcat(name, "_");
1663                strcat(name, method.name);
1664
1665                DeclareMethod(curExternal, method, name);
1666
1667                back = curContext;
1668                // THIS SpecDeclFromString HERE SHOULD WORK WITH THE METHOD TEMPLATE PARAMETERS...
1669                curContext = (method._class.symbol) ? ((Symbol)method._class.symbol).ctx : globalContext;
1670                // Cast function to its type
1671                {
1672                   Context context = SetupTemplatesContext(method._class);
1673
1674                   decl = SpecDeclFromString(method.dataTypeString, specs, MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), null)));
1675
1676                   FinishTemplatesContext(context);
1677                }
1678                curContext = back;
1679                if(method.dataType && !method.dataType.staticMethod)
1680                {
1681                   Declarator funcDecl = GetFuncDecl(decl);
1682
1683                   if(!funcDecl.function.parameters)
1684                      funcDecl.function.parameters = MkList();
1685                   {
1686                      TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
1687                      Specifier firstSpec = firstParam ? firstParam.qualifiers->first : null;
1688
1689                      if(firstParam && firstSpec && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
1690                      {
1691                         funcDecl.function.parameters->Remove(funcDecl.function.parameters->first);
1692                         FreeTypeName(firstParam);
1693                      }
1694                   }
1695
1696                   if(method.dataType.thisClass && !strcmp(method.dataType.thisClass.string, "class"))
1697                   {
1698                      TypeName param;
1699                      typedObject = true;
1700
1701                      param = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null));
1702                      param.qualifiers->Insert(null, MkSpecifier(CONST));
1703                      funcDecl.function.parameters->Insert(null, param);
1704                      // Testing this for any_object::
1705                      if(!method.dataType.extraParam)
1706                      {
1707                         funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null)), MkDeclaratorPointer(MkPointer(null,null), null)));
1708                         DeclareStruct(curExternal, "ecere::com::Class", false, true);
1709                      }
1710                   }
1711                   else
1712                   {
1713                      funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(
1714                         /*MkClassName*/MkSpecifierName(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)), null));
1715                   }
1716                }
1717
1718                typeName = MkTypeName(specs, decl);
1719
1720                if(memberExp && memberExp.member.exp.expType)
1721                {
1722                   Type type = memberExp.member.exp.expType;
1723
1724                   if(type.kind == classType && type._class && type._class.registered)
1725                   {
1726                      Class regClass = type._class.registered;
1727                      ClassType classType = regClass.type;
1728                      if(classType != normalClass || !strcmp(regClass.dataTypeString, "char *") || (method.dataType.byReference))// TESTING THIS OUT: && !memberExp.member.exp.expType.classObjectType)
1729                         argClass = regClass;
1730                   }
1731                   else if(type.kind == subClassType)
1732                   {
1733                      argClass = FindClass("ecere::com::Class").registered;
1734                   }
1735                   else if((type.kind == arrayType || type.kind == pointerType) && type.type && type.type.kind == charType)
1736                   {
1737                      argClass = FindClass("char *").registered;
1738                   }
1739                   else if(type.kind == pointerType)
1740                   {
1741                      argClass = eSystem_FindClass(privateModule, "uintptr");
1742                      FreeType(memberExp.member.exp.expType);
1743                      memberExp.member.exp.expType = ProcessTypeString("uintptr", false);
1744                      memberExp.member.exp.byReference = true;
1745                   }
1746                   else
1747                   {
1748                      char string[1024] = "";
1749                      Symbol classSym;
1750                      PrintTypeNoConst(type, string, false, true);
1751                      classSym = FindClass(string);
1752                      if(classSym) argClass = classSym.registered;
1753                   }
1754
1755                   /*
1756                   if(!_class && argClass && strcmp(argClass.fullName, "class"))
1757                      _class = argClass;
1758                   */
1759                }
1760
1761                {
1762                   Type type = memberExp ? memberExp.member.exp.expType : null;
1763                   Class regClass = (type && type.kind == classType && type._class) ? type._class.registered : null;
1764                   char className[1024];
1765
1766                   // Added !exp.call.exp.expType.methodClass
1767                   if(!expCallExp.expType.methodClass && !_class && type && type.classObjectType)
1768                      strcpy(className, "class");
1769                   else
1770                   {
1771                      Class cl = _class;
1772                      // TESTING: Moved this here...
1773                      if(!cl && argClass && strcmp(argClass.fullName, "class"))
1774                         cl = argClass;
1775                      if(!cl)
1776                         cl = regClass;
1777                      if(!cl)
1778                         // TODO: Unhandled case here, what should happen?
1779                         cl = class(int);
1780
1781                      // To avoid declaring classes templatized after this class template (e.g. public struct Iterator<class T, class IT = int> { Container<T, IT> container; } )
1782                      if(cl.templateClass && !_class && expCallExp.expType._class && !expCallExp.expType.methodClass &&
1783                         (type.kind == subClassType || (regClass && regClass.type == normalClass && strcmp(regClass.dataTypeString, "char *"))))
1784                         cl = cl.templateClass;
1785
1786                      // Need the class itself here...
1787                      strcpy(className, "__ecereClass_");
1788                      FullClassNameCat(className, cl.fullName, true);
1789
1790                      if(!cl.symbol)
1791                         cl.symbol = FindClass(cl.fullName);
1792
1793                      DeclareClass(curExternal, cl.symbol, className);
1794                   }
1795
1796                   if(type && type.kind == subClassType && !_class && !expCallExp.expType.methodClass && memberExp)
1797                   {
1798                      expCallExp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1799                         MkExpIndex(MkExpPointer(CopyExpression(memberExp.member.exp), MkIdentifier("_vTbl")),
1800                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1801
1802                      handleNullVMethod = true;
1803                   }
1804                   else if(_class || expCallExp.expType.methodClass || !memberExp ||
1805                          !regClass || regClass.type != normalClass || !strcmp(regClass.dataTypeString, "char *"))
1806                   {
1807                      if(!memberExp)
1808                         FreeExpression(expCallExp);
1809                      expCallExp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1810                         MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl")),
1811                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1812
1813                      handleNullVMethod = true;
1814                   }
1815                   else
1816                   {
1817                      // TOCHECK: Added this if statement here for File::OnSerialize to be calling the instance's own Seek function,
1818                      // as opposed to the File class vTbl one
1819
1820                      // ({ Instance __internal_ClassInst = e; __internal_ClassInst ? __internal_ClassInst._vTbl : __ecereClass_...; })
1821                      Expression vTblExp;
1822                      Context context = PushContext();
1823                      OldList * specs;
1824                      OldList * declList = MkListOne(MkDeclaration(
1825                               (specs = MkListOne(MkSpecifierName("Instance"))),
1826                               MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_ClassInst")),
1827                                  MkInitializerAssignment(CopyExpression(memberExp.member.exp))))));
1828                      OldList * stmtList = MkListOne(MkExpressionStmt(MkListOne(MkExpCondition(
1829                               MkExpIdentifier(MkIdentifier("__internal_ClassInst")),
1830                               MkListOne(MkExpPointer(MkExpIdentifier(MkIdentifier("__internal_ClassInst")), MkIdentifier("_vTbl"))),
1831                               MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl"))))));
1832
1833                      vTblExp = MkExpExtensionCompound(MkCompoundStmt(declList, stmtList));
1834
1835                      if(type.specConst)
1836                         specs->Insert(null, MkSpecifier(CONST));
1837
1838                      vTblExp.loc = exp.loc;
1839                      vTblExp.compound.compound.context = context;
1840                      PopContext(context);
1841
1842                      expCallExp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1843                         MkExpIndex(vTblExp, MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1844
1845                      handleNullVMethod = true;
1846                   }
1847                }
1848             }
1849             else
1850             {
1851                char name[1024];
1852                strcpy(name, "__ecereMethod_");
1853                FullClassNameCat(name, method._class.fullName, false);
1854                strcat(name, "_");
1855                strcat(name, method.name);
1856
1857                if(!memberExp)
1858                   FreeExpression(expCallExp);
1859                expCallExp = MkExpIdentifier(MkIdentifier(name));
1860                DeclareMethod(curExternal, method, name);
1861                if(memberExp && memberExp.expType && method.dataType)
1862                {
1863                   expCallExp.expType = method.dataType;
1864                   method.dataType.refCount++;
1865                }
1866             }
1867             if(memberExp && (!memberExp.member.exp || !memberExp.member.exp.expType || memberExp.member.exp.expType.kind != subClassType))
1868             {
1869                if(method.dataType && !method.dataType.staticMethod && !method.dataType.extraParam)
1870                {
1871                   if(!arguments)
1872                      arguments = MkList();
1873
1874                   // Testing this (COMMENTED OUT TESTING, CALLING METHODS ON ENUM/UNIT ADDED & IN FRONT OF VARIABLES
1875                   /*
1876                   if(memberExp.member.exp.expType.kind != classType ||
1877                      memberExp.member.exp.expType._class.registered.type == enumClass ||
1878                      memberExp.member.exp.expType._class.registered.type == unitClass)
1879                   {
1880                      char typeString[1024] = "";
1881                      if(memberExp.member.exp.expType.kind != classType)
1882                         PrintType(memberExp.member.exp.expType, typeString, false, true);
1883                      else
1884                         strcpy(typeString, memberExp.member.exp.expType._class.registered.dataTypeString);
1885
1886                      // THIS WAS NASTY:
1887                      // memberExp.member.exp.expType.kind = classType;
1888                      // memberExp.member.exp.expType._class = FindClass(typeString);
1889
1890                      FreeType(memberExp.member.exp.expType);
1891                      memberExp.member.exp.expType = Type
1892                      {
1893                         kind = classType;
1894                         _class = FindClass(typeString);
1895                         refCount = 1;
1896                      };
1897
1898                      // Default to an int instead
1899                      if(!memberExp.member.exp.expType._class)
1900                      {
1901                         // TODO: Shouldn't get here...
1902                         memberExp.member.exp.expType.kind = TypeInt;
1903                      }
1904                   }
1905                   */
1906
1907                   if(typedObject && memberExp.member.exp && memberExp.member.exp.expType)
1908                   {
1909                      bool changeReference = false;
1910                      bool stillAddReferenceOp = false;
1911                      Expression memberExpMemberExp = CopyExpression(memberExp.member.exp);
1912                      Type expType = memberExp.member.exp.expType;
1913                      Class c = expType.kind == classType && expType._class ? expType._class.registered : null;
1914
1915                      // Patched so that class isn't considered SYSTEM...
1916                      if(argClass && (argClass.type == enumClass || argClass.type == unitClass || argClass.type == bitClass || argClass.type == systemClass) && strcmp(argClass.fullName, "class") &&
1917                         strcmp(argClass.fullName, "uintptr") && strcmp(argClass.fullName, "intptr"))
1918                         changeReference = true;
1919                      if(!expType.classObjectType && ( ( (expType.kind != pointerType && (!c || c.type == structClass) ) ) || method.dataType.byReference) ) // ADDED THIS FOR OnGetDataFromString
1920                      {
1921                         if(c && (c.type == normalClass || c.type == noHeadClass))
1922                            stillAddReferenceOp = true;
1923                         changeReference = true;
1924                      }
1925                      if(typedObject && expType.classObjectType && expType.byReference != method.dataType.byReference)
1926                         changeReference = true;
1927                      if(changeReference)
1928                      {
1929                         if(memberExp.member.exp.type == bracketsExp && memberExp.member.exp.list && memberExp.member.exp.list->count == 1 &&
1930                            ((Expression)memberExp.member.exp.list->first).type == opExp && ((Expression)memberExp.member.exp.list->first).op.op == '*' && !((Expression)memberExp.member.exp.list->first).op.exp1)
1931                         {
1932                            arguments->Insert(null, ((Expression)memberExp.member.exp.list->first).op.exp2);
1933                            ((Expression)memberExp.member.exp.list->first).op.exp2 = null;
1934                         }
1935                         else if(memberExp.member.exp.type == opExp && memberExp.member.exp.op.op == '*' && !memberExp.member.exp.op.exp1)
1936                         {
1937                            arguments->Insert(null, memberExp.member.exp.op.exp2);
1938                            memberExp.member.exp.op.exp2 = null;
1939                         }
1940                         else if(!memberExp.member.exp.byReference || stillAddReferenceOp)
1941                         {
1942                            // TESTING THIS... REUSE THIS CODE?
1943                            Expression checkedExp = memberExp.member.exp;
1944                            Expression parentExp = null;
1945                            Expression newExp;
1946                            bool disconnected = false;
1947                            while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list) || checkedExp.type == castExp)
1948                            {
1949                               parentExp = checkedExp;
1950
1951                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
1952                               {
1953                                  checkedExp = checkedExp.list->last;
1954                                  // Dissociate from memberExp which will get freed
1955                                  if(checkedExp && !disconnected)
1956                                  {
1957                                     parentExp.list->Remove(checkedExp);
1958                                     disconnected = true;
1959                                  }
1960                               }
1961                               else if(checkedExp.type == castExp)
1962                               {
1963                                  checkedExp = checkedExp.cast.exp;
1964                                  // Dissociate from memberExp which will get freed
1965                                  if(checkedExp && !disconnected)
1966                                  {
1967                                     checkedExp.cast.exp = null;
1968                                     disconnected = true;
1969                                  }
1970                               }
1971                            }
1972                            if(!parentExp)
1973                               nullMemberExp = true;
1974
1975                            if(typedObject && !expType.classObjectType && !stillAddReferenceOp)
1976                               newExp = checkedExp;
1977                            else
1978                            {
1979                               newExp = MkExpOp(null, '&', checkedExp);
1980                               newExp.byReference = true;
1981                            }
1982                            if(parentExp && (parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp))
1983                            {
1984                               parentExp.list->Remove(checkedExp);
1985                               parentExp.list->Add(newExp);
1986                            }
1987                            else if(parentExp && parentExp.type == castExp)
1988                            {
1989                               parentExp.cast.exp = newExp;
1990                               // Add a dereference level here
1991                               if(newExp.expType && newExp.expType.classObjectType)
1992                                  parentExp.cast.typeName.declarator = MkDeclaratorPointer(MkPointer(null, null), parentExp.cast.typeName.declarator);
1993                            }
1994                            if(typedObject && !expType.classObjectType)
1995                            {
1996                               Type destType { refCount = 1, kind = classType, classObjectType = ClassObjectType::anyObject };
1997                               FreeType((parentExp ? parentExp : newExp).expType);
1998                               FreeType((parentExp ? parentExp : newExp).destType);
1999                               (parentExp ? parentExp : newExp).expType = checkedExp.expType;
2000                               (parentExp ? parentExp : newExp).destType = destType;
2001                               if(checkedExp.expType) checkedExp.expType.refCount++;
2002                            }
2003                            arguments->Insert(null, parentExp ? parentExp : newExp);
2004                         }
2005                         else
2006                         {
2007                            arguments->Insert(null, memberExp.member.exp);
2008                            nullMemberExp = true;
2009                         }
2010                      }
2011                      else
2012                      {
2013                         arguments->Insert(null, memberExp.member.exp);
2014                         nullMemberExp = true;
2015                      }
2016
2017                      {
2018                         char className[1024];
2019                         Type type = memberExp.member.exp ? memberExp.member.exp.expType : null;
2020                         Class regClass = (type && type.kind == classType && type._class) ? type._class.registered : null;
2021                         Class cl = argClass ? argClass : regClass;
2022                         className[0] = 0;
2023
2024                         if(memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.classObjectType == ClassObjectType::typedObject)
2025                            strcpy(className, "class");
2026                         else if(cl)
2027                         {
2028                            // Need the class itself here...
2029                            strcpy(className, "__ecereClass_");
2030                            FullClassNameCat(className, cl.fullName, true);
2031
2032                            if(!cl.symbol)
2033                               cl.symbol = FindClass(cl.fullName);
2034                            DeclareClass(curExternal, cl.symbol, className);
2035                         }
2036
2037                         if(className[0])
2038                         {
2039                            if(memberExp && cl && cl.type == normalClass && (!type || type.byReference == false) && strcmp(cl.dataTypeString, "char *"))
2040                            {
2041                               // ({ Instance __internal_ClassInst = e; __internal_ClassInst ? __internal_ClassInst._class : __ecereClass_...; })
2042                               Expression c;
2043                               Context context = PushContext();
2044                               OldList * specs;
2045
2046                               c = MkExpExtensionCompound(MkCompoundStmt(
2047                                     MkListOne(MkDeclaration(
2048                                        (specs = MkListOne(MkSpecifierName("Instance"))),
2049                                        MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_ClassInst")),
2050                                           MkInitializerAssignment(memberExpMemberExp))))),
2051                                     MkListOne(MkExpressionStmt(MkListOne(MkExpCondition(
2052                                        MkExpIdentifier(MkIdentifier("__internal_ClassInst")),
2053                                        MkListOne(MkExpPointer(MkExpIdentifier(MkIdentifier("__internal_ClassInst")), MkIdentifier("_class"))),
2054                                        MkExpIdentifier(MkIdentifier(className))))))));
2055                               c.compound.compound.context = context;
2056                               PopContext(context);
2057
2058                               if(type.specConst)
2059                                  specs->Insert(null, MkSpecifier(CONST));
2060
2061                               arguments->Insert(null, c);
2062
2063                               memberExpMemberExp = null; // We used this
2064                            }
2065                            else
2066                               arguments->Insert(null, MkExpIdentifier(MkIdentifier(className)));
2067                         }
2068                      }
2069
2070                      if(memberExpMemberExp)
2071                         FreeExpression(memberExpMemberExp);
2072                   }
2073                   else
2074                   {
2075                      arguments->Insert(null, memberExp.member.exp);
2076                      nullMemberExp = true;
2077                   }
2078                }
2079             }
2080             /*else if(method->dataType)
2081             {
2082             }*/
2083             if(memberExp)
2084             {
2085                if(nullMemberExp)
2086                   memberExp.member.exp = null;
2087                FreeExpression(memberExp);
2088             }
2089          }
2090
2091          if(arguments)
2092          {
2093             for(e = arguments->first; e; e = e.next)
2094             {
2095                Type destType = (e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : e.destType;
2096                //if(e.destType && e.destType.kind == classType && e.destType._class && !strcmp(e.destType._class.string, "class"))
2097                //if(e.destType && (e.destType.classObjectType == ClassObjectType::typedObject || e.destType.classObjectType == anyObject))
2098                if(destType && (destType.classObjectType == ClassObjectType::typedObject || destType.classObjectType == anyObject))
2099                {
2100                   if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
2101                   ellipsisDestType = destType;
2102                   if(e && e.expType)
2103                   {
2104                      Type type = e.expType;
2105                      Class _class = null;
2106                      //Type destType = e.destType;
2107
2108                      if(type.kind == classType && type._class && type._class.registered)
2109                      {
2110                         _class = type._class.registered;
2111                      }
2112                      else if(type.kind == subClassType)
2113                      {
2114                         _class = FindClass("ecere::com::Class").registered;
2115                      }
2116                      else if((type.kind == arrayType || type.kind == pointerType) && type.type && type.type.kind == charType)
2117                      {
2118                         _class = FindClass("char *").registered;
2119                      }
2120                      else if(type.kind == pointerType)
2121                      {
2122                         _class = eSystem_FindClass(privateModule, "uintptr");
2123                         FreeType(e.expType);
2124                         e.expType = ProcessTypeString("uintptr", false);
2125                         // Assume null pointers means 'no object' rather than an object holding a null pointer
2126                         e.byReference = true;
2127                      }
2128                      else
2129                      {
2130                         char string[1024] = "";
2131                         Symbol classSym;
2132                         PrintTypeNoConst(type, string, false, true);
2133                         classSym = FindClass(string);
2134                         if(classSym) _class = classSym.registered;
2135                         // if(!class) _class = eSystem_FindClass(privateModule, "int");
2136                      }
2137
2138                      if((_class && (_class.type == enumClass || _class.type == unitClass || _class.type == bitClass || _class.type == systemClass) && strcmp(_class.fullName, "class") && strcmp(_class.fullName, "uintptr") && strcmp(_class.fullName, "intptr")) || // Patched so that class isn't considered SYSTEM...
2139                         (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != intPtrType && type.kind != subClassType && type.kind != arrayType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
2140                         destType.byReference)))
2141                      {
2142                         //if(!_class || strcmp(_class.fullName, "String"))     // TESTING THIS WITH NEW String class...
2143                         //if(!_class || strcmp(_class.fullName, "char *"))     // TESTING THIS WITH NEW String class...
2144                         // TESTING WITHOUT THE ABOVE NOW!
2145                         {
2146                            Expression checkedExp;
2147                            Expression parentExp;
2148                            Expression newExp;
2149
2150                            checkedExp = e;
2151                            parentExp = exp;
2152                            while(checkedExp && (((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp))
2153                            {
2154                               parentExp = checkedExp;
2155                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
2156                               {
2157                                  if(checkedExp.type == extensionCompoundExp)
2158                                  {
2159                                     checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
2160                                  }
2161                                  else
2162                                     checkedExp = checkedExp.list->last;
2163                               }
2164                               else if(checkedExp.type == castExp)
2165                                  checkedExp = checkedExp.cast.exp;
2166                            }
2167
2168                            if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
2169                            {
2170                               /*
2171                               Expression newExp = e.op.exp2;
2172                               arguments->Insert(e.prev, newExp);
2173                               arguments->Remove(e);
2174                               e.op.exp2 = null;
2175                               FreeExpContents(e);
2176                               e = newExp;
2177                               */
2178                               newExp = checkedExp.op.exp2;
2179                               checkedExp.op.exp2 = null;
2180                               FreeExpContents(checkedExp);
2181
2182                               if(e.expType && e.expType.passAsTemplate)
2183                               {
2184                                  char size[100];
2185                                  ComputeTypeSize(e.expType);
2186                                  sprintf(size, "%d", e.expType.size);   // BOOTSTRAP FIX
2187                                  newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
2188                                     MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
2189                                        MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
2190                               }
2191
2192                               if(parentExp.type == callExp)
2193                               {
2194                                  arguments->Insert(e.prev, newExp);
2195                                  arguments->Remove(e);
2196                                  e = newExp;
2197                               }
2198                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
2199                               {
2200                                  parentExp.list->Remove(checkedExp);
2201                                  parentExp.list->Add(newExp);
2202                               }
2203                               else if(parentExp.type == castExp)
2204                               {
2205                                  // NEW CODE: BETTER WAY TO DO THIS? To prevent (double)(double *)
2206                                  if(parentExp.destType && parentExp.destType.kind == ellipsisType)
2207                                  {
2208                                     FreeTypeName(parentExp.cast.typeName);
2209                                     parentExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null));
2210                                  }
2211                                  parentExp.cast.exp = newExp;
2212                               }
2213                               else if(parentExp.type == extensionCompoundExp)
2214                               {
2215                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2216                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2217                               }
2218                               e.byReference = true;
2219
2220                               FreeType(checkedExp.expType);
2221                               FreeType(checkedExp.destType);
2222                               delete checkedExp;
2223                            }
2224                            else if((!e.byReference && (!e.expType || !e.expType.classObjectType) ) || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
2225                            {
2226                               Expression checkedExp;
2227                               Expression parentExp;
2228                               Expression newExp;
2229
2230                               {
2231                                  // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
2232                                  bool hasAddress =
2233                                     e.type == identifierExp ||
2234                                     (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
2235                                     (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
2236                                     (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
2237                                     e.type == indexExp;
2238
2239                                  if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
2240                                  {
2241                                     Context context = PushContext();
2242                                     Declarator decl;
2243                                     OldList * specs = MkList();
2244                                     char typeString[1024];
2245                                     Expression newExp { };
2246
2247                                     typeString[0] = '\0';
2248                                     *newExp = *e;
2249
2250                                     // TOCHECK: Should this read e.destType ???
2251
2252                                     if(exp.destType) exp.destType.refCount++;
2253                                     // if(exp.expType) exp.expType.refCount++;
2254                                     newExp.prev = null;
2255                                     newExp.next = null;
2256                                     newExp.expType = null;
2257
2258                                     PrintTypeNoConst(e.expType, typeString, false, true);
2259                                     decl = SpecDeclFromString(typeString, specs, null);
2260                                     newExp.destType = ProcessType(specs, decl);
2261
2262                                     curContext = context;
2263                                     e.type = extensionCompoundExp;
2264
2265                                     // We need a current compound for this
2266                                     if(curCompound)
2267                                     {
2268                                        char name[100];
2269                                        OldList * stmts = MkList();
2270                                        sprintf(name, "__internalValue%03X", internalValueCounter++);
2271                                        if(!curCompound.compound.declarations)
2272                                           curCompound.compound.declarations = MkList();
2273                                        curCompound.compound.declarations->Insert(null, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null))));
2274                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', newExp))));
2275                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier(name)))));
2276                                        e.compound = MkCompoundStmt(null, stmts);
2277                                     }
2278                                     else
2279                                        printf("libec: compiler error, curCompound is null in ApplyAnyObjectLogic\n");
2280
2281                                     /*
2282
2283                                     e.compound = MkCompoundStmt(
2284                                        MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))),
2285                                        MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
2286                                     */
2287
2288                                     e.compound.compound.context = context;
2289                                     PopContext(context);
2290                                     curContext = context.parent;
2291                                  }
2292                               }
2293
2294                               // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
2295                               checkedExp = e;
2296                               parentExp = exp;
2297                               while(checkedExp && (((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp))
2298                               {
2299                                  parentExp = checkedExp;
2300                                  if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
2301                                  {
2302                                     if(checkedExp.type == extensionCompoundExp)
2303                                     {
2304                                        checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
2305                                     }
2306                                     else
2307                                        checkedExp = checkedExp.list->last;
2308                                  }
2309                                  else if(checkedExp.type == castExp)
2310                                     checkedExp = checkedExp.cast.exp;
2311                               }
2312                               {
2313                                  Expression i;
2314                                  newExp = MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)), (i = MkExpOp(null, '&', checkedExp)));
2315                                  i.byReference = true;
2316                                  newExp.byReference = true;
2317                               }
2318                               if(parentExp.type == callExp)
2319                               {
2320                                  arguments->Insert(e.prev, newExp);
2321                                  arguments->Remove(e);
2322                                  e = newExp;
2323                               }
2324                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
2325                               {
2326                                  parentExp.list->Remove(checkedExp);
2327                                  parentExp.list->Add(newExp);
2328                               }
2329                               else if(parentExp.type == castExp)
2330                                  parentExp.cast.exp = newExp;
2331                               else if(parentExp.type == bracketsExp || parentExp.type == extensionCompoundExp)
2332                               {
2333                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2334                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2335                               }
2336                            }
2337                         }
2338                      }
2339
2340                      if(destType.classObjectType == ClassObjectType::typedObject)
2341                      {
2342                         char className[1024];
2343                         // Need the class itself here...
2344                         if(!_class && type.kind == pointerType && type.type && type.type.kind == charType)
2345                            _class = eSystem_FindClass(privateModule, "String");
2346                         if(!_class) _class = eSystem_FindClass(privateModule, "int");
2347
2348                         if(!strcmp(_class.name, "class"))
2349                         {
2350                            // Already inside a typed_object function, pass the class through
2351                            strcpy(className, "class");
2352                         }
2353                         else
2354                         {
2355                            strcpy(className, "__ecereClass_");
2356                            FullClassNameCat(className, _class.fullName, true);
2357
2358                            if(!_class.symbol)
2359                               _class.symbol = FindClass(_class.fullName);
2360
2361                            DeclareClass(curExternal, _class.symbol, className);
2362                         }
2363
2364                         if(_class.type == normalClass && destType.byReference == false && strcmp(_class.dataTypeString, "char *"))
2365                         {
2366                            // ({ Instance __internal_ClassInst = e; __internal_ClassInst ? __internal_ClassInst._class : __ecereClass_...; })
2367                            Expression c;
2368                            Context context = PushContext();
2369
2370                            // Work around to avoid repeating the BuiltInContainer just to get the type
2371                            // (a bit messy since we already transformed our expression to an extensionInitializerExp in earlier pass)
2372                            if(_class.templateClass && !strcmp(_class.templateClass.name, "Container") &&
2373                               e.list && e.list->first &&
2374                               ((Expression)e.list->first).type == castExp &&
2375                               ((Expression)e.list->first).cast.exp &&
2376                               ((Expression)e.list->first).cast.exp.type == opExp &&
2377                               ((Expression)e.list->first).cast.exp.op.op == '&' &&
2378                               ((Expression)e.list->first).cast.exp.op.exp2 &&
2379                               ((Expression)e.list->first).cast.exp.op.exp2.type == extensionInitializerExp)
2380                            {
2381                               arguments->Insert(e.prev, MkExpIdentifier(MkIdentifier(className)));
2382                            }
2383                            else
2384                            {
2385                               OldList * specs;
2386                               c = MkExpExtensionCompound(MkCompoundStmt(
2387                                     MkListOne(MkDeclaration(
2388                                        (specs = MkListOne(MkSpecifierName("Instance"))),
2389                                        MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_ClassInst")),
2390                                           MkInitializerAssignment(CopyExpression(e)))))),
2391                                     MkListOne(MkExpressionStmt(MkListOne(MkExpCondition(
2392                                        MkExpIdentifier(MkIdentifier("__internal_ClassInst")),
2393                                        MkListOne(MkExpPointer(MkExpIdentifier(MkIdentifier("__internal_ClassInst")), MkIdentifier("_class"))),
2394                                        MkExpIdentifier(MkIdentifier(className))))))));
2395                               c.compound.compound.context = context;
2396                               PopContext(context);
2397
2398                               if(type.specConst)
2399                                  specs->Insert(null, MkSpecifier(CONST));
2400
2401                               arguments->Insert(e.prev, c);
2402                            }
2403                         }
2404                         else
2405                            arguments->Insert(e.prev, MkExpIdentifier(MkIdentifier(className)));
2406                      }
2407                   }
2408                }
2409                {
2410 #ifdef _DEBUG
2411                   //char debugString[4096] = "";
2412                   //PrintExpression(e, debugString);
2413 #endif
2414                   // If expression type is a simple class, make it an address
2415                   FixReference(e, !destType || !destType.declaredWithStruct);
2416                }
2417             }
2418             if(ellipsisDestType)
2419             {
2420                if(usedEllipsis ||
2421                   (expCallExp.expType && expCallExp.expType.kind == functionType && expCallExp.expType.params.last &&
2422                    ((Type)expCallExp.expType.params.last).kind == ellipsisType))
2423                {
2424                   arguments->Insert(arguments->last, MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null),null)),MkExpConstant("0")));
2425                }
2426             }
2427          }
2428
2429          if(handleNullVMethod)
2430          {
2431             Expression compoundExp;
2432             Context context = PushContext();
2433             OldList * declList = MkList();
2434             OldList * stmtList = MkList();
2435             TypeName castTypeName;
2436             OldList * specs = MkList();
2437             Specifier spec;
2438
2439             for(spec = typeName.qualifiers ? typeName.qualifiers->first : null; spec; spec = spec.next)
2440             {
2441                if(spec.type != extendedSpecifier)
2442                   specs->Add(CopySpecifier(spec));
2443             }
2444
2445             if(typeName.declarator.type == pointerDeclarator)
2446             {
2447                Pointer p = typeName.declarator.pointer.pointer.pointer;
2448                castTypeName = MkTypeName(specs, CopyDeclarator(typeName.declarator.declarator.declarator.declarator));
2449                while(p)
2450                {
2451                   Pointer pp;
2452                   for(pp = castTypeName.declarator.pointer.pointer; pp.pointer; pp = pp.pointer);
2453                   pp.pointer = MkPointer(null, null);
2454                   pp.qualifiers = CopyList(p.qualifiers, CopySpecifier);
2455                   p = p.pointer;
2456                }
2457             }
2458             else
2459                castTypeName = MkTypeName(specs, CopyDeclarator(typeName.declarator.declarator.declarator.declarator));
2460
2461             compoundExp = MkExpExtensionCompound(MkCompoundStmt(declList, stmtList));
2462
2463             declList->Add(MkDeclaration(CopyList(typeName.qualifiers, CopySpecifier),
2464                MkListOne(MkInitDeclarator(PlugDeclarator(CopyDeclarator(typeName.declarator), MkDeclaratorIdentifier(MkIdentifier("__internal_VirtualMethod"))), null))));
2465
2466             stmtList->Add(MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier("__internal_VirtualMethod")), '=', expCallExp))));
2467             stmtList->Add(MkExpressionStmt(MkListOne(MkExpCondition(
2468                MkExpIdentifier(MkIdentifier("__internal_VirtualMethod")),
2469                MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("__internal_VirtualMethod")), arguments)), MkExpCast(castTypeName, MkExpConstant("1"))))));
2470
2471             compoundExp.loc = exp.loc;
2472             compoundExp.compound.compound.context = context;
2473             PopContext(context);
2474
2475             exp.type = bracketsExp;
2476             exp.list = MkListOne(compoundExp);
2477          }
2478          else
2479          {
2480             exp.call.exp = expCallExp;
2481             exp.call.arguments = arguments;
2482          }
2483          break;
2484       }
2485       case memberExp:
2486       {
2487          bool changeToPtr = false;
2488          bool noHead = false;
2489          Type type = exp.member.exp ? exp.member.exp.expType : null;
2490          Specifier memberClassSpecifier = exp.member.member ? exp.member.member._class : null;
2491          if(exp.member.member) exp.member.member._class = null;
2492
2493          if(type && type.kind == templateType)
2494          {
2495             Type baseType = ProcessTemplateParameterType(type.templateParameter);
2496             if(baseType) type = baseType;
2497          }
2498          if(type && exp.member.member && !type.directClassAccess)
2499          {
2500             Class _class = exp.member.member.classSym ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
2501             Property prop = null;
2502             ClassProperty classProperty = null;
2503             Method method = null;
2504             Class convertTo = null;
2505             DataMember member = null;
2506             DataMember subMemberStack[256];
2507             int subMemberStackPos = 0;
2508             bool thisPtr = exp.member.thisPtr;
2509             if(type.kind == subClassType && exp.member.exp.type == classExp)
2510                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
2511
2512             // TEST: exp.member.exp.tempCount = Max(exp.tempCount, exp.member.exp.tempCount);
2513
2514             if(!_class)
2515             {
2516                // DANGER: Buffer overflow
2517                char string[2048] = "";
2518                Symbol classSym;
2519                PrintTypeNoConst(type, string, false, true);
2520                classSym = FindClass(string);
2521                _class = classSym ? classSym.registered : null;
2522             }
2523
2524             if(_class && exp.member.memberType == dataMember)
2525             {
2526                if(!thisPtr && !exp.member.member.classSym)
2527                   member = eClass_FindDataMember(_class, exp.member.member.string, null, subMemberStack, &subMemberStackPos);
2528                if(!member)
2529                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, subMemberStack, &subMemberStackPos);
2530             }
2531             else if(_class && exp.member.memberType == propertyMember)
2532             {
2533                if(!thisPtr && !exp.member.member.classSym)
2534                   prop = eClass_FindProperty(_class, exp.member.member.string, null);
2535                if(!prop)
2536                   prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
2537                if(prop && (exp.usage.usageRef ||
2538                   (exp.usage.usageGet && !prop.Get && !prop.conversion) ||
2539                   (exp.usage.usageDelete && !prop.Set && !prop.conversion)))
2540                {
2541                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, subMemberStack, &subMemberStackPos);
2542                   if(member)
2543                   {
2544                      exp.member.memberType = dataMember;
2545                      prop = null;
2546                   }
2547                   else
2548                   {
2549                      if(exp.usage.usageRef)
2550                         Compiler_Error($"cannot obtain address of property\n");
2551                      else if(!prop.Get)
2552                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2553                      else if(exp.usage.usageDelete)
2554                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2555                   }
2556                }
2557             }
2558             else if(_class && exp.member.memberType == methodMember)
2559             {
2560                if(!thisPtr)
2561                   method = eClass_FindMethod(_class, exp.member.member.string, null);
2562                if(!method)
2563                   method = eClass_FindMethod(_class, exp.member.member.string, privateModule);
2564             }
2565             else if(_class && exp.member.memberType == reverseConversionMember)
2566             {
2567                convertTo = _class;
2568                _class = FindClass(exp.member.member.string).registered;
2569                // prop = eClass_FindProperty(_class, convertTo.name, privateModule);
2570                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
2571             }
2572             else if(_class && exp.member.memberType == classPropertyMember)
2573             {
2574                classProperty = eClass_FindClassProperty(_class, exp.member.member.string);
2575             }
2576             if(prop)
2577             {
2578                // Only process Gets here, Set is processed in opExp's '='
2579                if(exp.usage.usageGet)
2580                {
2581                   if(prop.Get)
2582                   {
2583                      char getName[1024], setName[1024];
2584                      Expression ptr = exp.member.exp;
2585                      Class propertyClass;
2586                      char * nameToUse = convertTo ? setName : getName;
2587
2588                      FreeIdentifier(exp.member.member);
2589
2590                      // Process this here since it won't be processed at the end...
2591                      exp.member.exp.usage.usageGet = true;
2592                      ProcessExpression(exp.member.exp);
2593                      // TEST: exp.tempCount = exp.member.exp.tempCount;
2594
2595                      DeclareProperty(curExternal, prop, setName, getName);
2596                      //propertyClass = convertTo ? _class : ((Symbol)prop.symbol)._class;
2597                      propertyClass = convertTo ? _class :
2598                         ((((Symbol)prop.symbol).type && ((Symbol)prop.symbol).type.kind == classType) ? ((Symbol)prop.symbol).type._class.registered : ((Symbol)prop.symbol)._class);
2599
2600                      if(propertyClass && propertyClass.type == bitClass)
2601                      {
2602                         // Bit classes shouldn't have properties except for conversions...
2603                         OldList * args = MkList();
2604                         if(exp.usage.usageDeepGet)
2605                         {
2606                            char className[1024];
2607                            Declaration decl;
2608                            Declarator declarator;
2609                            OldList * specs = MkList(), * decls = MkList();
2610                            Expression tempExp;
2611
2612                            // Make a declaration in the closest compound statement
2613                            // (Do not reuse (since using address for function calls)...)
2614                            sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2615                            declarator =
2616                               SpecDeclFromString(propertyClass.dataTypeString, specs,
2617                                  MkDeclaratorIdentifier(MkIdentifier(className)));
2618
2619                            ListAdd(decls, MkInitDeclarator(declarator, null));
2620
2621                            decl = MkDeclaration(specs, decls);
2622                            if(!curCompound.compound.declarations)
2623                               curCompound.compound.declarations = MkList();
2624                            curCompound.compound.declarations->Insert(null, decl);
2625
2626                            tempExp = QMkExpId(className);
2627                            tempExp.expType = MkClassType(propertyClass.fullName);
2628
2629                            exp.op.exp1 = tempExp;
2630                            exp.op.exp2 = MkExpCall(QMkExpId(nameToUse), args);
2631                            exp.op.op = '=';
2632                            exp.type = opExp;
2633                         }
2634                         else
2635                         {
2636                            exp.type = callExp;
2637                            exp.call.exp = QMkExpId(nameToUse);
2638                            exp.call.arguments = args;
2639                         }
2640                         ListAdd(args, FixReference(ptr, true));
2641                      }
2642                      else if(propertyClass && propertyClass.type == unitClass)
2643                      {
2644                         OldList * args = MkList();
2645                         ListAdd(args, FixReference(ptr, true));
2646                         exp.type = callExp;
2647                         exp.call.exp = QMkExpId(nameToUse);
2648                         exp.call.arguments = args;
2649                      }
2650                      else if(propertyClass && propertyClass.type == structClass)
2651                      {
2652                         OldList * args = MkList();
2653                         char className[1024];
2654                         Declaration decl;
2655                         OldList * specs = MkList(), * decls = MkList();
2656                         Expression tempExp;
2657
2658                         // Make a declaration in the closest compound statement
2659                         // (Do not reuse (since using address for function calls)...)
2660
2661                         className[0] = 0;
2662                         FullClassNameCat(className, propertyClass.fullName, false); //true);
2663                         DeclareStruct(curExternal, propertyClass.fullName, false, true);
2664
2665                         //ListAdd(specs, MkSpecifierName(className));
2666                         ListAdd(specs, MkStructOrUnion(structSpecifier, MkIdentifier(className), null));
2667
2668                         sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2669
2670                         ListAdd(decls, MkInitDeclarator(
2671                            MkDeclaratorIdentifier(MkIdentifier(className)), null));
2672
2673                         decl = MkDeclaration(specs, decls);
2674                         if(curCompound)
2675                         {
2676                            if(!curCompound.compound.declarations)
2677                               curCompound.compound.declarations = MkList();
2678                            curCompound.compound.declarations->Insert(null, decl);
2679                         }
2680
2681                         tempExp = QMkExpId(className);
2682                         tempExp.expType = MkClassType(propertyClass.fullName);
2683
2684                         if(convertTo)
2685                         {
2686                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2687                            ListAdd(args, FixReference(ptr, true));
2688                         }
2689                         else
2690                         {
2691                            ListAdd(args, FixReference(ptr, true));
2692                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2693                         }
2694
2695                         if(exp.usage.usageDeepGet)
2696                         {
2697                            exp.type = callExp;
2698                            exp.call.exp = QMkExpId(nameToUse);
2699                            exp.call.arguments = args;
2700
2701                            FreeExpression(tempExp);
2702                         }
2703                         else
2704                         {
2705                            exp.type = bracketsExp;
2706                            exp.list = MkList();
2707                            ListAdd(exp.list, MkExpCall(QMkExpId(nameToUse),args));
2708                            if(exp.usage.usageMember)
2709                            {
2710                               ListAdd(exp.list, FixReference(tempExp, true));
2711                               exp.byReference = true;
2712                            }
2713                            else
2714                               ListAdd(exp.list, tempExp);
2715                         }
2716                      }
2717                      else
2718                      {
2719                         exp.type = callExp;
2720                         exp.call.exp = QMkExpId(nameToUse);
2721                         exp.call.arguments = MkList();
2722                         ListAdd(exp.call.arguments, FixReference(ptr, true));
2723                      }
2724                   }
2725                   else if(prop.conversion)
2726                   {
2727                      void * prev = exp.prev, * next = exp.next;
2728                      *exp = *exp.member.exp;
2729                      exp.prev = prev;
2730                      exp.next = next;
2731                   }
2732                }
2733             }
2734             else if(classProperty)
2735             {
2736                // Only process Gets here, Set is processed in opExp's '='
2737                if(exp.usage.usageGet)
2738                {
2739                   if(classProperty.Get)
2740                   {
2741                      Identifier id = exp.member.member;
2742                      Expression classExp = exp.member.exp;
2743                      OldList * args = MkList();
2744
2745                      exp.type = castExp;
2746                      // Class Property
2747                      if(exp.expType)
2748                      {
2749                         char typeString[2048];
2750                         OldList * specs = MkList();
2751                         Declarator decl;
2752                         typeString[0] = 0;
2753                         PrintType(exp.expType, typeString, false, false);
2754                         decl = SpecDeclFromString(typeString, specs, null);
2755                         exp.cast.typeName = MkTypeName(specs, decl);
2756                      }
2757                      else
2758                         exp.cast.typeName = QMkType("uint64", null);
2759                      exp.cast.exp = MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eClass_GetProperty")), args);
2760                      if(exp.expType.isPointerType)
2761                         exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
2762
2763                      ListAdd(args, classExp);
2764                      {
2765                         char * s = QMkString(id.string);
2766                         ListAdd(args, MkExpString(s));
2767                         delete s;
2768                      }
2769                      FreeIdentifier(id);
2770
2771                      ProcessExpression(exp);
2772                      return;
2773                   }
2774                }
2775             }
2776             else if(method)
2777             {
2778                // Get the function address if it's not called
2779                if((exp.usage.usageGet || exp.member.exp.expType.kind == subClassType) && !(exp.usage.usageCall))
2780                {
2781                   char name[1024];
2782
2783                   FreeIdentifier(exp.member.member);
2784
2785                   // Process this here since it won't be processed at the end...
2786                   exp.member.exp.usage.usageGet = true;
2787                   ProcessExpression(exp.member.exp);
2788                   // TEST: exp.tempCount = exp.member.exp.tempCount;
2789
2790                   if(method.type == virtualMethod)
2791                   {
2792                      strcpy(name, "__ecereVMethodID_");
2793                      FullClassNameCat(name, method._class.fullName, false);
2794                      strcat(name, "_");
2795                      strcat(name, method.name);
2796                      exp.type = indexExp;
2797                      if(memberClassSpecifier)
2798                      {
2799                         char className[1024];
2800                         // Need the class itself here...
2801                         strcpy(className, "__ecereClass_");
2802                         FullClassNameCat(className, _class.fullName, true);
2803
2804                         if(!_class.symbol)
2805                            _class.symbol = FindClass(_class.fullName);
2806                         DeclareClass(curExternal, _class.symbol, className);
2807
2808                         FreeExpression(exp.member.exp);
2809                         exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl"));
2810                      }
2811                      else
2812                      {
2813                         if(exp.thisPtr && _class.type != normalClass)
2814                         {
2815                            FreeExpression(exp.member.exp);
2816                            exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("_vTbl"));
2817                         }
2818                         else
2819                            exp.index.exp = MkExpPointer(exp.member.exp, MkIdentifier("_vTbl"));
2820                      }
2821                      exp.index.index = MkListOne(QMkExpId(name));
2822                      DeclareMethod(curExternal, method, name);
2823                   }
2824                   else
2825                   {
2826                      FreeExpression(exp.member.exp);
2827                      exp.type = identifierExp;
2828                      strcpy(name, "__ecereMethod_");
2829                      FullClassNameCat(name, method._class.fullName, false);
2830                      strcat(name, "_");
2831                      strcat(name, method.name);
2832                      exp.identifier = MkIdentifier(name);
2833                      DeclareMethod(curExternal, method, name);
2834                   }
2835                }
2836             }
2837             else if(member)
2838             {
2839                if(subMemberStackPos)
2840                {
2841                   int i;
2842                   DataMember parentMember = null;
2843                   String s, prefix = null;
2844                   for(i = 0; i < subMemberStackPos; i++)
2845                   {
2846                      DataMember curMember = subMemberStack[i];
2847                      DataMember m;
2848                      int anonID = 1;
2849                      for(m = parentMember ? parentMember.members.first : _class.membersAndProperties.first; m; m = m.next)
2850                      {
2851                         if(m && !m.isProperty && (m.type == unionMember || m.type == structMember) && !m.name)
2852                         {
2853                            if(m == curMember)
2854                               break;
2855                            anonID++;
2856                         }
2857                      }
2858
2859                      if(prefix)
2860                      {
2861                         s = prefix;
2862                         prefix = PrintString(prefix, ".__anon", anonID);
2863                         delete s;
2864                      }
2865                      else
2866                         prefix = PrintString("__anon", anonID);
2867                      parentMember = curMember;
2868                   }
2869
2870                   s = exp.member.member.string;
2871                   exp.member.member.string = PrintString(prefix, ".", s);
2872                   delete prefix;
2873                   delete s;
2874                }
2875                // Process this here since it won't be processed at the end...
2876                if(exp.usage.usageGet)
2877                {
2878                   exp.member.exp.usage.usageGet = true;   // Recently added this... is it ok?
2879                }
2880                ProcessExpression(exp.member.exp);
2881                // TEST: exp.tempCount = exp.member.exp.tempCount;
2882
2883                if(type.kind == classType && type._class && type._class.registered)
2884                   DeclareStruct(curExternal, type._class.registered.fullName, false, true);
2885
2886                // TESTING THIS NOHEAD STUFF...
2887                if(_class.type == noHeadClass)
2888                {
2889                   noHead = true;
2890                }
2891                else if(_class.type == structClass)
2892                {
2893                   changeToPtr = true;
2894                }
2895                else if(_class.type == bitClass)
2896                {
2897                   OldList * list = MkList();
2898                   char mask[32], shift[10];
2899                   OldList * specs = MkList();
2900                   BitMember bitMember = (BitMember) member;
2901                   Declarator decl = SpecDeclFromString(bitMember.dataTypeString, specs, null);
2902                   TypeName type = MkTypeName(specs, decl);
2903                   if(bitMember.mask > MAXDWORD)
2904                      sprintf(mask, FORMAT64HEXLL, bitMember.mask);
2905                   else
2906                      sprintf(mask, FORMAT64HEX, bitMember.mask);
2907                   sprintf(shift, "%d", bitMember.pos);
2908
2909                   FreeIdentifier(exp.member.member);
2910
2911                   // ((type) ((color & mask) >> bitPos))
2912                   ListAdd(list, MkExpCast(type, MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(MkListOne(
2913                      MkExpOp(exp.member.exp, '&', MkExpConstant(mask)))), RIGHT_OP,
2914                         MkExpConstant(shift))))));
2915
2916                   exp.type = bracketsExp;
2917                   exp.list = list;
2918                }
2919                else if(_class.type == unitClass)
2920                {
2921                }
2922                else
2923                {
2924                   // If it's a this pointer, replace by precomputed shortcut
2925                   if(exp.member.exp.type == identifierExp && thisPtr && type.kind == classType && (!exp.member.exp.expType || !exp.member.exp.expType.typedByReference))
2926                   {
2927                      char pointerName[1024];
2928
2929                      strcpy(pointerName, "__ecerePointer_");
2930                      FullClassNameCat(pointerName, type._class.registered.fullName, false);
2931                      if(exp.member.exp.identifier)
2932                         FreeIdentifier(exp.member.exp.identifier);
2933                      exp.member.exp.identifier = MkIdentifier(pointerName);
2934                   }
2935                   // Otherwise, access the data the hard way
2936                   else
2937                   {
2938                      Expression bytePtr, e;
2939                      Expression checkedExp;
2940                      char structName[1024];
2941                      char className[1024];
2942                      strcpy(className, "__ecereClass_");
2943                      FullClassNameCat(className, member._class.fullName, true);
2944
2945                      // classExp = QMkExpId(className);
2946
2947                      if(!member._class.symbol)
2948                         member._class.symbol = FindClass(member._class.fullName);
2949
2950                      DeclareClass(curExternal, member._class.symbol, className);
2951                      DeclareStruct(curExternal, member._class.fullName, false, true);
2952
2953                      structName[0] = 0;
2954                      FullClassNameCat(structName, member._class.fullName, false);
2955
2956                      checkedExp = exp.member.exp;
2957                      while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list && checkedExp.list->count == 1) ||
2958                            checkedExp.type == castExp)
2959                      {
2960                         if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
2961                            checkedExp = checkedExp.list->last;
2962                         else if(checkedExp.type == castExp)
2963                            checkedExp = checkedExp.cast.exp;
2964                      }
2965
2966                      if(checkedExp.type != identifierExp &&
2967                         checkedExp.type != constantExp &&      // Added this here... Might mess up if we need address?
2968                         checkedExp.type != memberExp && checkedExp.type != pointerExp)
2969                      {
2970                         char ecereTemp[100];
2971                         Statement compound;
2972                         Context context = PushContext();
2973                         if(exp.member.exp.tempCount > exp.tempCount)
2974                            exp.tempCount = exp.member.exp.tempCount;
2975
2976                         exp.tempCount++;
2977                         curExternal.function.tempCount = Max(curExternal.function.tempCount, exp.tempCount);
2978                         sprintf(ecereTemp, "__ecTemp%d", exp.tempCount);
2979                         curContext = context;
2980                         compound = MkCompoundStmt(
2981                            MkListOne(MkDeclaration(MkListOne(MkSpecifier(CHAR)), MkListOne(MkInitDeclarator(
2982                               MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier(ecereTemp))),
2983                                  MkInitializerAssignment(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)), QBrackets(exp.member.exp))))))), null);
2984                         if(member._class.fixed)
2985                         {
2986                            Class c = member._class.templateClass ? member._class.templateClass : member._class;
2987                            if(c.offset)
2988                            {
2989                               Expression se;
2990
2991                               if(c.offset == c.base.structSize)
2992                               {
2993                                  se = MkExpClassSize(MkSpecifierName(c.base.fullName));
2994                                  ProcessExpressionType(se);
2995                                  se.isConstant = false;
2996                               }
2997                               else
2998                               {
2999                                  char string[256];
3000                                  sprintf(string, "%d", c.offset);
3001                                  se = MkExpConstant(string);
3002                               }
3003                               e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', se));
3004                            }
3005                            else
3006                               e = QMkExpId(ecereTemp);
3007                         }
3008                         else
3009                         {
3010                            e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+',
3011                               MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
3012                         }
3013
3014                         compound.compound.context = context;
3015                         compound.compound.statements = MkListOne(MkExpressionStmt(MkListOne(
3016                            QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
3017                               MkDeclaratorPointer(MkPointer(null, null), null)), e)))));
3018
3019                         exp.member.exp =  MkExpExtensionCompound(compound);
3020
3021                         PopContext(context);
3022                         curContext = context.parent;
3023                      }
3024                      else
3025                      {
3026                         bytePtr = MkExpCast(QMkType("char", QMkPtrDecl(null)), /*CopyExpression(*/exp.member.exp/*)*/);
3027                         // DISABLED BECAUSE PREVENTS GETTING ADDRESS OF MEMBERS WITH ADDRESS 0
3028                         /*
3029                         e = QBrackets(QMkExpCond(exp.member.exp,
3030                            QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(classExp, MkIdentifier("offset")))),
3031                            MkExpConstant("0")));
3032                         */
3033
3034                         // if(class.fixed)
3035                         if(member._class.fixed)
3036                         {
3037                            Class c = member._class.templateClass ? member._class.templateClass : member._class;
3038                            if(c.offset)
3039                            {
3040                               Expression se;
3041
3042                               if(c.offset == c.base.structSize)
3043                               {
3044                                  se = MkExpClassSize(MkSpecifierName(c.base.fullName));
3045                                  ProcessExpressionType(se);
3046                                  se.isConstant = false;
3047                               }
3048                               else
3049                               {
3050                                  char string[256];
3051                                  sprintf(string, "%d", c.offset);
3052                                  se = MkExpConstant(string);
3053                               }
3054
3055                               e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', se)));
3056                            }
3057                            else
3058                               e = bytePtr;
3059                         }
3060                         else
3061                            e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(QMkExpId(className), MkIdentifier("offset")))));
3062
3063                         // exp.member.exp = QBrackets(MkExpCast(QMkType(structName, QMkPtrDecl(null)), e));
3064                         exp.member.exp = QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), QMkPtrDecl(null)), e));
3065                      }
3066                   }
3067                   exp.type = pointerExp;
3068                }
3069             }
3070          }
3071
3072          // Take Out Any Class Specifier (Should have been used by now)
3073          FreeSpecifier(memberClassSpecifier);
3074
3075          // Just moved this at the end... How is it?
3076          if(exp.member.exp && (exp.type == memberExp || exp.type == pointerExp))
3077          {
3078             exp.member.exp.usage.usageGet = true;
3079             exp.member.exp.usage.usageMember = true;
3080             exp.member.exp.tempCount = exp.tempCount;
3081             ProcessExpression(exp.member.exp);
3082             exp.tempCount = exp.member.exp.tempCount;
3083             if((changeToPtr && exp.member.exp.byReference) || noHead)
3084                exp.type = pointerExp;
3085          }
3086          break;
3087       }
3088       case extensionCompoundExp:
3089       {
3090          Expression e = ((Statement)exp.compound.compound.statements->last).expressions->last;
3091          if(e)
3092             e.usage |= exp.usage & ExpUsage { usageGet = true, usageArg = true, usageMember = true };
3093
3094          ProcessStatement(exp.compound);
3095
3096          /*if(((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference)
3097             exp.byReference = ((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference;*/
3098          break;
3099       }
3100       case pointerExp:
3101       {
3102          exp.member.exp.usage.usageGet = true;
3103          ProcessExpression(exp.member.exp);
3104          break;
3105       }
3106       case typeSizeExp:
3107       {
3108          Specifier spec = exp.typeName.qualifiers ? exp.typeName.qualifiers->first : null;
3109          if(spec && spec.type == templateTypeSpecifier && !exp.typeName.declarator)
3110          {
3111             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, false);
3112             if(argExp)
3113             {
3114                Expression classExp;
3115
3116                FreeTypeName(exp.typeName);
3117
3118                classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
3119
3120                ProcessExpressionType(classExp);
3121                ProcessExpression(classExp);
3122
3123                exp.type = bracketsExp;
3124                exp.list = MkListOne(MkExpMember(classExp, MkIdentifier("typeSize")));
3125
3126                ProcessExpressionType(exp);
3127                ProcessExpression(exp);
3128             }
3129          }
3130          break;
3131       }
3132       case castExp:
3133       {
3134          if(exp.cast.exp)
3135          {
3136             exp.cast.exp.usage |= exp.usage & ExpUsage { usageGet = true, usageMember = true };
3137             ProcessExpression(exp.cast.exp);
3138             // TESTING THIS
3139             if(exp.cast.exp.byReference)
3140                exp.byReference = exp.cast.exp.byReference;
3141             if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass &&
3142                exp.cast.exp.expType && (exp.cast.exp.expType.kind == pointerType || exp.cast.exp.expType.kind == arrayType || (
3143                   exp.cast.exp.expType.kind == classType && exp.cast.exp.expType._class && exp.cast.exp.expType._class.registered &&
3144                      !strcmp(exp.cast.exp.expType._class.registered.dataTypeString, "char *")) ) )
3145                exp.byReference = true;
3146          }
3147          // Moved this to 1.5...
3148          //exp.expType = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
3149          break;
3150       }
3151       case conditionExp:
3152       {
3153          Expression e;
3154          if(exp.usage.usageGet)
3155             exp.cond.cond.usage.usageGet = true;
3156          ProcessExpression(exp.cond.cond);
3157          for(e = exp.cond.exp->first; e; e = e.next)
3158          {
3159             if(!e.next && exp.usage.usageGet) e.usage.usageGet = true;
3160             ProcessExpression(e);
3161          }
3162          if(exp.usage.usageGet)
3163             exp.cond.elseExp.usage.usageGet = true;
3164          ProcessExpression(exp.cond.elseExp);
3165          break;
3166       }
3167       case classExp:
3168       {
3169          // Need the class itself here...
3170          if(exp._classExp.specifiers && exp._classExp.specifiers->first && ((Specifier)exp._classExp.specifiers->first).type == templateTypeSpecifier)
3171          {
3172             Specifier spec = exp._classExp.specifiers->first;
3173             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, true);
3174             if(argExp)
3175             {
3176                FreeList(exp._classExp.specifiers, FreeSpecifier);
3177                if(exp._classExp.decl)
3178                   FreeDeclarator(exp._classExp.decl);
3179
3180                exp.type = memberExp; //pointerExp;
3181                exp.member.exp = argExp;
3182                exp.member.member = MkIdentifier("dataTypeClass");
3183                exp.member.memberType = dataMember;
3184
3185                ProcessExpressionType(argExp);
3186                ProcessExpressionType(exp);
3187                ProcessExpression(exp);
3188             }
3189          }
3190          else
3191          {
3192             char className[1024];
3193             char * string = StringFromSpecDecl(exp._classExp.specifiers, exp._classExp.decl);
3194             Symbol classSym = FindClass(string);
3195
3196             strcpy(className, "__ecereClass_");
3197             FullClassNameCat(className, string, true);      // TODO: Verify this
3198
3199             DeclareClass(curExternal, classSym, className);
3200             delete string;
3201
3202             FreeList(exp._classExp.specifiers, FreeSpecifier);
3203             if(exp._classExp.decl)
3204                FreeDeclarator(exp._classExp.decl);
3205
3206             exp.type = identifierExp;
3207             exp.identifier = MkIdentifier(className);
3208          }
3209          break;
3210       }
3211       case vaArgExp:
3212       {
3213          ProcessExpression(exp.vaArg.exp);
3214          break;
3215       }
3216       case extensionInitializerExp:
3217       {
3218          ProcessInitializer(exp.initializer.initializer);
3219          break;
3220       }
3221    }
3222    FixRefExp(exp);
3223
3224    if(exp.needTemplateCast != 2 && (exp.needTemplateCast == 1 || (exp.expType && (exp.expType.kind == templateType || exp.expType.passAsTemplate))))
3225    {
3226       Expression nbExp = GetNonBracketsExp(exp);
3227       Expression inner = GetInnerExp(nbExp);
3228
3229       if((!exp.expType || exp.expType.kind != templateType || nbExp.type != castExp) && !exp.usage.usageRef &&
3230          (!exp.destType || (!exp.destType.truth && (exp.destType.kind != templateType || (exp.destType.templateParameter && (exp.destType.templateParameter.dataTypeString || exp.destType.templateParameter.dataType))))) &&
3231          (exp.usage.usageDelete || exp.usage.usageGet || exp.usage.usageArg) &&
3232          (!exp.destType || (!exp.destType.passAsTemplate && exp.expType && (exp.expType.kind != pointerType || (exp.destType.kind == pointerType || exp.destType.kind == intPtrType)) && ((exp.destType.kind != pointerType && exp.destType.kind != intPtrType) || exp.expType.kind == pointerType))) &&
3233          !inner.needCast && inner.type != opExp)
3234       {
3235          Expression e = MoveExpContents(exp);
3236          Declarator decl;
3237          OldList * specs = MkList();
3238          char typeString[1024];
3239          bool castingToDest = false;
3240          bool pointerCastExp = false;
3241
3242          typeString[0] = '\0';
3243
3244          e.needTemplateCast = 2;
3245          inner.needTemplateCast = 2;
3246          nbExp.needTemplateCast = 2;
3247          if(exp.usage.usageDelete)
3248             strcpy(typeString, "void *");
3249          else
3250          {
3251             if(exp.expType.kind == templateType && exp.expType.templateParameter && exp.expType.templateParameter.dataTypeString)
3252                strcpy(typeString, exp.expType.templateParameter.dataTypeString);
3253             else
3254                PrintType(exp.expType, typeString, false, false);
3255          }
3256
3257          decl = SpecDeclFromString(typeString, specs, null);
3258
3259          if(specs && specs->first && ((Specifier)specs->first).type == templateTypeSpecifier &&
3260             exp.destType && !exp.destType.passAsTemplate && exp.destType.kind == templateType && exp.destType.templateParameter && (exp.destType.templateParameter.dataTypeString || exp.destType.templateParameter.dataType) && !exp.usage.usageArg)
3261          {
3262             if(decl) FreeDeclarator(decl);
3263             FreeList(specs, FreeSpecifier);
3264             if(exp.destType.templateParameter.dataTypeString)
3265             {
3266                specs = MkList();
3267                strcpy(typeString, exp.destType.templateParameter.dataTypeString);
3268                decl = SpecDeclFromString(typeString, specs, null);
3269             }
3270             else
3271             {
3272                specs = CopyList(exp.destType.templateParameter.dataType.specifiers, CopySpecifier);
3273                decl = CopyDeclarator(exp.destType.templateParameter.dataType.decl);
3274             }
3275
3276             castingToDest = true;
3277          }
3278
3279          e.destType = exp.destType;
3280          if(exp.destType)
3281             exp.destType.refCount++;
3282
3283          exp.type = bracketsExp;
3284
3285          {
3286             Specifier spec = specs ? specs->first : null;
3287             TemplateParameter tp = (spec && spec.type == templateTypeSpecifier) ? spec.templateParameter : null;
3288             Type type = castingToDest ? exp.destType : exp.expType;
3289             bool specsDeclPointer = (spec.type == nameSpecifier && strcmp(spec.name, "uint64")) ||
3290                (decl && decl.type == pointerDeclarator) ||
3291                (tp && tp.dataType &&
3292                   ( (tp.dataType.decl && tp.dataType.decl.type == pointerDeclarator) ||
3293                     (tp.dataType.specifiers && ((Specifier)tp.dataType.specifiers->first).type == nameSpecifier && strcmp(((Specifier)tp.dataType.specifiers->first).name, "uint64")) ) );
3294             pointerCastExp = type ? ((type.kind == templateType && specsDeclPointer) || type.isPointerType) : specsDeclPointer;
3295          }
3296
3297          if(pointerCastExp)
3298          {
3299             e = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), MkExpBrackets(MkListOne(e)));
3300             e.needTemplateCast = 2;
3301          }
3302          exp.list = MkListOne(MkExpCast(MkTypeName(specs, decl), MkExpBrackets(MkListOne(e))));
3303          if(exp.destType && pointerCastExp == (exp.destType.passAsTemplate ||
3304             (!exp.destType.isPointerType || (exp.destType.kind == templateType && (!exp.destType.templateParameter || (!exp.destType.templateParameter.dataType && !exp.destType.templateParameter.dataTypeString))))))
3305             exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), decl), MkExpBrackets(exp.list)));
3306          exp.needTemplateCast = 2;
3307       }
3308    }
3309    yylloc = oldyylloc;
3310 }
3311
3312 static void ProcessInitializer(Initializer init)
3313 {
3314    switch(init.type)
3315    {
3316       case expInitializer:
3317          if(init.exp)
3318          {
3319             init.exp.usage.usageGet = true;
3320             ProcessExpression(init.exp);
3321             if(init.exp.destType && init.exp.destType.kind == classType && init.exp.destType._class &&
3322                init.exp.destType._class.registered && init.exp.destType._class.registered.type == noHeadClass)
3323             {
3324                FixReference(init.exp, true);
3325             }
3326             else if(init.exp.destType && init.exp.destType.kind == classType)
3327                FixReference(init.exp, false);
3328          }
3329          break;
3330       case listInitializer:
3331       {
3332          if(init.list)
3333          {
3334             Initializer i;
3335             for(i = init.list->first; i; i = i.next)
3336                ProcessInitializer(i);
3337          }
3338          break;
3339       }
3340    }
3341 }
3342
3343 static void ProcessDeclaration(Declaration decl)
3344 {
3345    switch(decl.type)
3346    {
3347       case initDeclaration:
3348       {
3349          if(decl.declarators)
3350          {
3351             InitDeclarator d;
3352
3353             for(d = decl.declarators->first; d; d = d.next)
3354             {
3355                if(d.initializer)
3356                   ProcessInitializer(d.initializer);
3357             }
3358          }
3359          break;
3360       }
3361    }
3362 }
3363
3364 static void ProcessStatement(Statement stmt)
3365 {
3366    switch(stmt.type)
3367    {
3368       case labeledStmt:
3369          ProcessStatement(stmt.labeled.stmt);
3370          break;
3371       case caseStmt:
3372          if(stmt.caseStmt.exp)
3373          {
3374             stmt.caseStmt.exp.usage.usageGet = true;
3375
3376             // This expression should be constant...
3377             ProcessExpression(stmt.caseStmt.exp);
3378          }
3379          if(stmt.caseStmt.stmt)
3380             ProcessStatement(stmt.caseStmt.stmt);
3381          break;
3382       case compoundStmt:
3383       {
3384          if(stmt.compound.context)
3385          {
3386             Declaration decl;
3387             Statement s;
3388             Statement prevCompound = curCompound;
3389             Context prevContext = curContext;
3390
3391             if(!stmt.compound.isSwitch)
3392             {
3393                curCompound = stmt;
3394                curContext = stmt.compound.context;
3395             }
3396
3397             if(stmt.compound.declarations)
3398             {
3399                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
3400                   ProcessDeclaration(decl);
3401             }
3402             if(stmt.compound.statements)
3403             {
3404                for(s = stmt.compound.statements->first; s; s = s.next)
3405                   ProcessStatement(s);
3406             }
3407             curContext = prevContext;
3408             curCompound = prevCompound;
3409          }
3410          break;
3411       }
3412       case expressionStmt:
3413       {
3414          Expression exp;
3415          if(stmt.expressions)
3416          {
3417             for(exp = stmt.expressions->first; exp; exp = exp.next)
3418             {
3419                ProcessExpression(exp);
3420             }
3421          }
3422          break;
3423       }
3424       case ifStmt:
3425       {
3426          if(stmt.ifStmt.exp)
3427          {
3428             Expression exp;
3429
3430             ((Expression)stmt.ifStmt.exp->last).usage.usageGet = true;
3431             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
3432             {
3433                ProcessExpression(exp);
3434             }
3435          }
3436          if(stmt.ifStmt.stmt)
3437             ProcessStatement(stmt.ifStmt.stmt);
3438          if(stmt.ifStmt.elseStmt)
3439             ProcessStatement(stmt.ifStmt.elseStmt);
3440          break;
3441       }
3442       case switchStmt:
3443       {
3444          Expression exp;
3445          if(stmt.switchStmt.exp && stmt.switchStmt.exp->last)
3446          {
3447             ((Expression)stmt.switchStmt.exp->last).usage.usageGet = true;
3448             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
3449             {
3450                ProcessExpression(exp);
3451             }
3452          }
3453          ProcessStatement(stmt.switchStmt.stmt);
3454          break;
3455       }
3456       case whileStmt:
3457       {
3458          Expression exp;
3459          if(stmt.whileStmt.exp && stmt.whileStmt.exp->last)
3460          {
3461             ((Expression)stmt.whileStmt.exp->last).usage.usageGet = true;
3462             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
3463             {
3464                ProcessExpression(exp);
3465             }
3466          }
3467          ProcessStatement(stmt.whileStmt.stmt);
3468          break;
3469       }
3470       case doWhileStmt:
3471       {
3472          Expression exp;
3473          if(stmt.doWhile.exp && stmt.doWhile.exp->last)
3474          {
3475             ((Expression)stmt.doWhile.exp->last).usage.usageGet = true;
3476             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
3477             {
3478                ProcessExpression(exp);
3479             }
3480          }
3481          if(stmt.doWhile.stmt)
3482             ProcessStatement(stmt.doWhile.stmt);
3483          break;
3484       }
3485       case forStmt:
3486       {
3487          Expression exp;
3488          if(stmt.forStmt.init)
3489             ProcessStatement(stmt.forStmt.init);
3490
3491          if(stmt.forStmt.check)
3492          {
3493             if(stmt.forStmt.check.expressions)
3494             {
3495                ((Expression)stmt.forStmt.check.expressions->last).usage.usageGet = true;
3496             }
3497             ProcessStatement(stmt.forStmt.check);
3498          }
3499          if(stmt.forStmt.increment)
3500          {
3501             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
3502             {
3503                ProcessExpression(exp);
3504             }
3505          }
3506          if(stmt.forStmt.stmt)
3507             ProcessStatement(stmt.forStmt.stmt);
3508          break;
3509       }
3510       case gotoStmt:
3511          break;
3512       case continueStmt:
3513          break;
3514       case breakStmt:
3515          break;
3516       case returnStmt:
3517       {
3518          Expression exp;
3519          if(stmt.expressions)
3520          {
3521             ((Expression)stmt.expressions->last).usage.usageGet = true;
3522             for(exp = stmt.expressions->first; exp; exp = exp.next)
3523             {
3524                ProcessExpression(exp);
3525                // TOCHECK: This was added 2013/02/09 as part of 64 bit port for structs in class properties to automatically be returned by reference
3526                if(!exp.next && exp.destType && exp.destType.byReference)
3527                   FixReference(exp, true);
3528             }
3529          }
3530          break;
3531       }
3532       case badDeclarationStmt:
3533       {
3534          ProcessDeclaration(stmt.decl);
3535          break;
3536       }
3537       case asmStmt:
3538       {
3539          AsmField field;
3540          if(stmt.asmStmt.inputFields)
3541          {
3542             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
3543                if(field.expression)
3544                   ProcessExpression(field.expression);
3545          }
3546          if(stmt.asmStmt.outputFields)
3547          {
3548             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
3549                if(field.expression)
3550                   ProcessExpression(field.expression);
3551          }
3552          if(stmt.asmStmt.clobberedFields)
3553          {
3554             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
3555                if(field.expression)
3556                   ProcessExpression(field.expression);
3557          }
3558          break;
3559       }
3560    }
3561 }
3562
3563 static void ProcessFunction(FunctionDefinition function)
3564 {
3565    if(function.body)
3566       ProcessStatement(function.body);
3567 }
3568
3569 static void ProcessMemberInitData(MemberInit member)
3570 {
3571    if(member.initializer)
3572       ProcessInitializer(member.initializer);
3573 }
3574
3575 static void ProcessInstantiation(Instantiation inst)
3576 {
3577    if(inst.members)
3578    {
3579       MembersInit members;
3580       for(members = inst.members->first; members; members = members.next)
3581       {
3582          if(members.type == dataMembersInit)
3583          {
3584             if(members.dataMembers)
3585             {
3586                MemberInit member;
3587                for(member = members.dataMembers->first; member; member = member.next)
3588                   ProcessMemberInitData(member);
3589             }
3590          }
3591          else if(members.type == methodMembersInit)
3592          {
3593             ProcessFunction((FunctionDefinition)members.function);
3594          }
3595       }
3596    }
3597 }
3598
3599 /////////// MEMBER ACCESS PASS /////////////////////////////////////////////
3600 public void ProcessMemberAccess()
3601 {
3602    External external;
3603    for(external = ast->first; external; external = external.next)
3604    {
3605       curExternal = external;
3606       // There shouldn't be any class member access here anyways...
3607       if(external.type == declarationExternal)
3608       {
3609          if(external.declaration)
3610             ProcessDeclaration(external.declaration);
3611       }
3612    }
3613
3614    for(external = ast->first; external; external = external.next)
3615    {
3616       curExternal = external;
3617       if(external.type == functionExternal)
3618       {
3619          ProcessFunction(external.function);
3620       }
3621       else if(external.type == declarationExternal)
3622       {
3623          if(external.declaration)
3624             ProcessDeclaration(external.declaration);
3625       }
3626       else if(external.type == classExternal)
3627       {
3628          ClassDefinition _class = external._class;
3629          if(_class.definitions)
3630          {
3631             ClassDef def;
3632             Class regClass = _class.symbol.registered;
3633
3634             // Process all functions
3635             for(def = _class.definitions->first; def; def = def.next)
3636             {
3637                if(def.type == functionClassDef)
3638                {
3639                   curExternal = def.function.declarator.symbol.pointerExternal;
3640                   ProcessFunction((FunctionDefinition)def.function);
3641                }
3642                else if(def.type == declarationClassDef && def.decl.type == instDeclaration)
3643                {
3644                   ProcessInstantiation(def.decl.inst);
3645                }
3646                else if(def.type == defaultPropertiesClassDef && def.defProperties)
3647                {
3648                   MemberInit defProperty;
3649
3650                   // Add this to the context
3651                   Symbol thisSymbol
3652                   {
3653                      string = CopyString("this");
3654                      type = MkClassType(regClass.fullName);
3655                   };
3656                   globalContext.symbols.Add((BTNode)thisSymbol);
3657
3658                   for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
3659                   {
3660                      //thisClass = regClass;
3661                      ProcessMemberInitData(defProperty); //, regClass, &id);
3662                      //thisClass = null;
3663                   }
3664
3665                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3666                   globalContext.symbols.Remove((BTNode)thisSymbol);
3667                   FreeSymbol(thisSymbol);
3668                }
3669                else if(def.type == propertyClassDef && def.propertyDef)
3670                {
3671                   PropertyDef prop = def.propertyDef;
3672
3673                   // Add this to the context
3674                   Symbol thisSymbol
3675                   {
3676                      string = CopyString("this");
3677                      type = MkClassType(regClass.fullName);
3678                   };
3679                   globalContext.symbols.Add((BTNode)thisSymbol);
3680
3681                   //thisClass = regClass;
3682                   if(prop.setStmt)
3683                   {
3684                      curExternal = prop.symbol.externalSet;
3685                      ProcessStatement(prop.setStmt);
3686                   }
3687                   if(prop.getStmt)
3688                   {
3689                      curExternal = prop.symbol.externalGet;
3690                      ProcessStatement(prop.getStmt);
3691                   }
3692                   if(prop.issetStmt)
3693                   {
3694                      curExternal = prop.symbol.externalIsSet;
3695                      ProcessStatement(prop.issetStmt);
3696                   }
3697
3698                   //thisClass = null;
3699
3700                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3701                   globalContext.symbols.Remove((BTNode)thisSymbol);
3702                   FreeSymbol(thisSymbol);
3703                }
3704                else if(def.type == classPropertyClassDef && def.propertyDef)
3705                {
3706                   PropertyDef prop = def.propertyDef;
3707
3708                   //thisClass = regClass;
3709                   if(prop.setStmt)
3710                   {
3711                      curExternal = prop.symbol.externalSet;
3712                      ProcessStatement(prop.setStmt);
3713                   }
3714                   if(prop.getStmt)
3715                   {
3716                      curExternal = prop.symbol.externalGet;
3717                      ProcessStatement(prop.getStmt);
3718                   }
3719                   //thisClass = null;
3720                }
3721                else if(def.type == propertyWatchClassDef && def.propertyWatch)
3722                {
3723                   PropertyWatch propertyWatch = def.propertyWatch;
3724
3725                   // Add this to the context
3726                   Symbol thisSymbol
3727                   {
3728                      string = CopyString("this");
3729                      type = MkClassType(regClass.fullName);
3730                   };
3731                   globalContext.symbols.Add((BTNode)thisSymbol);
3732
3733                   //thisClass = regClass;
3734                   if(propertyWatch.compound)
3735                   {
3736                      Symbol thisSymbol
3737                      {
3738                         string = CopyString("this");
3739                         type = MkClassType(regClass.fullName);
3740                      };
3741                      propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
3742                      curExternal = null;
3743                      ProcessStatement(propertyWatch.compound);
3744                   }
3745                   // thisClass = null;
3746
3747                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3748                   globalContext.symbols.Remove((BTNode)thisSymbol);
3749                   FreeSymbol(thisSymbol);
3750                }
3751             }
3752          }
3753       }
3754    }
3755 }