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