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