compiler/libec: Added support for String s; s.OnGetString() (#974)
[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                      Class regClass = type._class.registered;
1671                      ClassType classType = regClass.type;
1672                      if(classType != normalClass || !strcmp(regClass.dataTypeString, "char *") || (method.dataType.byReference))// TESTING THIS OUT: && !memberExp.member.exp.expType.classObjectType)
1673                         argClass = regClass;
1674                   }
1675                   else if(type.kind == subClassType)
1676                   {
1677                      argClass = FindClass("ecere::com::Class").registered;
1678                   }
1679                   else if((type.kind == arrayType || type.kind == pointerType) && type.type && type.type.kind == charType)
1680                   {
1681                      argClass = FindClass("char *").registered;
1682                   }
1683                   else if(type.kind == pointerType)
1684                   {
1685                      argClass = eSystem_FindClass(privateModule, "uintptr");
1686                      FreeType(memberExp.member.exp.expType);
1687                      memberExp.member.exp.expType = ProcessTypeString("uintptr", false);
1688                      memberExp.member.exp.byReference = true;
1689                   }
1690                   else
1691                   {
1692                      char string[1024] = "";
1693                      Symbol classSym;
1694                      PrintTypeNoConst(type, string, false, true);
1695                      classSym = FindClass(string);
1696                      if(classSym) argClass = classSym.registered;
1697                   }
1698
1699                   /*
1700                   if(!_class && argClass && strcmp(argClass.fullName, "class"))
1701                      _class = argClass;
1702                   */
1703                }
1704
1705                {
1706                   Type type = memberExp.member.exp.expType;
1707                   Class regClass = (type && type.kind == classType && type._class) ? type._class.registered : null; 
1708                   // *** Added !_class here
1709                   if(!exp.call.exp.expType.methodClass && (!memberExp || !_class) && type && type.classObjectType)
1710                   {
1711                      if(regClass && regClass.type == normalClass && strcmp(regClass.dataTypeString, "char *"))
1712                      {
1713                         // TOCHECK: Added this if statement here for File::OnSerialize to be calling the instance's own Seek function,
1714                         // as opposed to the File class vTbl one
1715                         exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1716                            MkExpIndex(MkExpPointer(MkExpBrackets(MkListOne(CopyExpression(memberExp.member.exp))), MkIdentifier("_vTbl")),
1717                            MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1718                      }
1719                      else
1720                      {
1721                         exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1722                            MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("_vTbl")),
1723                            MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1724                      }
1725                   }
1726                   else if(memberExp && !_class && exp.call.exp.expType._class &&
1727                         (type.kind == subClassType || (regClass && regClass.type == normalClass && strcmp(regClass.dataTypeString, "char *"))))
1728                   {
1729                      exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1730                         MkExpIndex(MkExpPointer(CopyExpression(memberExp.member.exp), MkIdentifier("_vTbl")),
1731                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1732                   }
1733                   else 
1734                   {
1735                      char className[1024];
1736
1737                      // TESTING: Moved this here...
1738                      if(!_class && argClass && strcmp(argClass.fullName, "class"))
1739                         _class = argClass;
1740
1741                      if(!_class)
1742                      {
1743                         // TODO: Unhandled case here, what should happen?
1744                         _class = class(int);
1745                      }
1746
1747                      // Need the class itself here...
1748                      strcpy(className, "__ecereClass_");
1749                      FullClassNameCat(className, _class.fullName, true);
1750                      MangleClassName(className);
1751
1752                      if(!_class.symbol)
1753                         _class.symbol = FindClass(_class.fullName);
1754
1755                      DeclareClass(_class.symbol, className);
1756
1757                      exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1758                         MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl")),
1759                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1760                   }
1761                }
1762             }
1763             else
1764             {
1765                char name[1024];
1766                strcpy(name, "__ecereMethod_");
1767                FullClassNameCat(name, method._class.fullName, false);
1768                strcat(name, "_");
1769                strcat(name, method.name);
1770
1771                exp.call.exp = MkExpIdentifier(MkIdentifier(name));
1772                DeclareMethod(method, name);
1773                if(memberExp && memberExp.expType && method.dataType)
1774                {
1775                   exp.call.exp.expType = method.dataType;
1776                   method.dataType.refCount++;
1777                }
1778             }
1779             if(memberExp && (!memberExp.member.exp || !memberExp.member.exp.expType || memberExp.member.exp.expType.kind != subClassType))
1780             {
1781                if(method.dataType && !method.dataType.staticMethod && !method.dataType.extraParam)
1782                {
1783                   if(!exp.call.arguments)
1784                      exp.call.arguments = MkList();
1785
1786                   // Testing this (COMMENTED OUT TESTING, CALLING METHODS ON ENUM/UNIT ADDED & IN FRONT OF VARIABLES
1787                   /*
1788                   if(memberExp.member.exp.expType.kind != classType || 
1789                      memberExp.member.exp.expType._class.registered.type == enumClass ||
1790                      memberExp.member.exp.expType._class.registered.type == unitClass)
1791                   {
1792                      char typeString[1024] = "";
1793                      if(memberExp.member.exp.expType.kind != classType)
1794                         PrintType(memberExp.member.exp.expType, typeString, false, true);
1795                      else
1796                         strcpy(typeString, memberExp.member.exp.expType._class.registered.dataTypeString);
1797
1798                      // THIS WAS NASTY:
1799                      // memberExp.member.exp.expType.kind = classType;
1800                      // memberExp.member.exp.expType._class = FindClass(typeString);
1801                      
1802                      FreeType(memberExp.member.exp.expType);
1803                      memberExp.member.exp.expType = Type
1804                      {
1805                         kind = classType;
1806                         _class = FindClass(typeString);
1807                         refCount = 1;
1808                      };
1809
1810                      // Default to an int instead
1811                      if(!memberExp.member.exp.expType._class)
1812                      {
1813                         // TODO: Shouldn't get here...
1814                         memberExp.member.exp.expType.kind = TypeInt;
1815                      }
1816                   }
1817                   */
1818                   
1819                   if(typedObject && memberExp.member.exp && memberExp.member.exp.expType)
1820                   {
1821                      bool changeReference = false;
1822
1823                      // Patched so that class isn't considered SYSTEM...
1824                      if(argClass && (argClass.type == enumClass || argClass.type == unitClass || argClass.type == bitClass || argClass.type == systemClass) && strcmp(argClass.fullName, "class") && 
1825                         strcmp(argClass.fullName, "uintptr") && strcmp(argClass.fullName, "intptr"))
1826                         changeReference = true;
1827                      if(!memberExp.member.exp.expType.classObjectType && 
1828                         (((
1829                            (memberExp.member.exp.expType.kind != pointerType && 
1830                               (memberExp.member.exp.expType.kind != classType || !memberExp.member.exp.expType._class || 
1831                                !memberExp.member.exp.expType._class.registered || memberExp.member.exp.expType._class.registered.type == structClass)))) ||
1832                            method.dataType.byReference)) // ADDED THIS FOR OnGetDataFromString
1833                         changeReference = true;
1834                      if(typedObject && memberExp.member.exp.expType.classObjectType && memberExp.member.exp.expType.byReference != method.dataType.byReference)
1835                         changeReference = true;
1836                      if(changeReference)
1837                      {
1838                         if(memberExp.member.exp.type == bracketsExp && memberExp.member.exp.list && memberExp.member.exp.list->count == 1 && 
1839                            ((Expression)memberExp.member.exp.list->first).type == opExp && ((Expression)memberExp.member.exp.list->first).op.op == '*' && !((Expression)memberExp.member.exp.list->first).op.exp1)
1840                         {
1841                            exp.call.arguments->Insert(null, ((Expression)memberExp.member.exp.list->first).op.exp2);
1842                            ((Expression)memberExp.member.exp.list->first).op.exp2 = null;
1843                         }
1844                         else if(memberExp.member.exp.type == opExp && memberExp.member.exp.op.op == '*' && !memberExp.member.exp.op.exp1)
1845                         {
1846                            exp.call.arguments->Insert(null, memberExp.member.exp.op.exp2);
1847                            memberExp.member.exp.op.exp2 = null;
1848                         }
1849                         else if(!memberExp.member.exp.byReference)
1850                         {
1851                            // TESTING THIS... REUSE THIS CODE?
1852                            Expression checkedExp = memberExp.member.exp;
1853                            Expression parentExp = null;
1854                            Expression newExp;
1855                            while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list) || checkedExp.type == castExp)
1856                            {
1857                               parentExp = checkedExp;
1858                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
1859                                  checkedExp = checkedExp.list->last;
1860                               else if(checkedExp.type == castExp)
1861                                  checkedExp = checkedExp.cast.exp;
1862                            }
1863                            newExp = (typedObject && !memberExp.member.exp.expType.classObjectType) ? checkedExp : MkExpOp(null, '&', checkedExp);
1864                            if(parentExp && (parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp))
1865                            {
1866                               parentExp.list->Remove(checkedExp);
1867                               parentExp.list->Add(newExp);
1868                            }
1869                            else if(parentExp && parentExp.type == castExp)
1870                            {
1871                               parentExp.cast.exp = newExp;
1872                               // Add a dereference level here
1873                               parentExp.cast.typeName.declarator = MkDeclaratorPointer(MkPointer(null, null), parentExp.cast.typeName.declarator);
1874                            }
1875                            if(typedObject && !memberExp.member.exp.expType.classObjectType)
1876                            {
1877                               Type destType { refCount = 1, kind = classType, classObjectType = ClassObjectType::anyObject };
1878                               (parentExp ? parentExp : newExp).expType = checkedExp.expType;
1879                               (parentExp ? parentExp : newExp).destType = destType;
1880                               if(checkedExp.expType) checkedExp.expType.refCount++;
1881                            }
1882                            exp.call.arguments->Insert(null, parentExp ? parentExp : newExp);
1883                         }
1884                         else
1885                            exp.call.arguments->Insert(null, memberExp.member.exp);
1886                      }
1887                      else
1888                         exp.call.arguments->Insert(null, memberExp.member.exp);
1889
1890                      //if(memberExp.member.exp && memberExp.member.exp.type == identifierExp && !strcmp(memberExp.member.exp.identifier.string, "this") && FindSymbol("class", curContext, topContext, false))
1891                      if(memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.classObjectType == ClassObjectType::typedObject)
1892                      {
1893                         exp.call.arguments->Insert(null, MkExpIdentifier(MkIdentifier("class")));
1894                      }
1895                      else
1896                      {
1897                         if(memberExp && !argClass)
1898                            exp.call.arguments->Insert(null, MkExpPointer(CopyExpression(memberExp.member.exp), MkIdentifier("_class")));
1899                         else
1900                         {
1901                            char className[1024];
1902                            // Need the class itself here...
1903                            strcpy(className, "__ecereClass_");
1904                            FullClassNameCat(className, argClass.fullName, true);
1905                            MangleClassName(className);
1906
1907                            if(!argClass.symbol)
1908                               argClass.symbol = FindClass(argClass.fullName);
1909                            DeclareClass(argClass.symbol, className);
1910                            exp.call.arguments->Insert(null, MkExpIdentifier(MkIdentifier(className)));
1911                         }
1912                      }
1913                   }
1914                   else
1915                      exp.call.arguments->Insert(null, memberExp.member.exp);
1916                   memberExp.member.exp = null;
1917                }
1918                FreeExpression(memberExp);
1919             }
1920             /*else if(method->dataType)
1921             {
1922             }*/
1923          }
1924          if(exp.call.arguments)
1925          {
1926             for(e = exp.call.arguments->first; e; e = e.next)
1927             {
1928                Type destType = (e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : e.destType;
1929                //if(e.destType && e.destType.kind == classType && e.destType._class && !strcmp(e.destType._class.string, "class"))
1930                //if(e.destType && (e.destType.classObjectType == ClassObjectType::typedObject || e.destType.classObjectType == anyObject))
1931                if(destType && (destType.classObjectType == ClassObjectType::typedObject || destType.classObjectType == anyObject))
1932                {
1933                   if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
1934                   ellipsisDestType = destType;
1935                   if(e && e.expType)
1936                   {
1937                      Type type = e.expType;
1938                      Class _class = null;
1939                      //Type destType = e.destType;
1940
1941                      if(type.kind == classType && type._class && type._class.registered)
1942                      {
1943                         _class = type._class.registered;
1944                      }
1945                      else if(type.kind == subClassType)
1946                      {
1947                         _class = FindClass("ecere::com::Class").registered;
1948                      }
1949                      else if((type.kind == arrayType || type.kind == pointerType) && type.type && type.type.kind == charType)
1950                      {
1951                         _class = FindClass("char *").registered;
1952                      }
1953                      else if(type.kind == pointerType)
1954                      {
1955                         _class = eSystem_FindClass(privateModule, "uintptr");
1956                         FreeType(e.expType);
1957                         e.expType = ProcessTypeString("uintptr", false);
1958                         // Assume null pointers means 'no object' rather than an object holding a null pointer
1959                         e.byReference = true;
1960                      }
1961                      else
1962                      {
1963                         char string[1024] = "";
1964                         Symbol classSym;
1965                         PrintTypeNoConst(type, string, false, true);
1966                         classSym = FindClass(string);
1967                         if(classSym) _class = classSym.registered;
1968                         // if(!class) _class = eSystem_FindClass(privateModule, "int");
1969                      }
1970
1971                      if((_class && (_class.type == enumClass || _class.type == unitClass || _class.type == bitClass || _class.type == systemClass) && strcmp(_class.fullName, "class") && strcmp(_class.fullName, "uintptr") && strcmp(_class.fullName, "intptr")) || // Patched so that class isn't considered SYSTEM...
1972                         (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != intPtrType && type.kind != subClassType && type.kind != arrayType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
1973                         destType.byReference)))
1974                      {
1975                         //if(!_class || strcmp(_class.fullName, "String"))     // TESTING THIS WITH NEW String class...
1976                         //if(!_class || strcmp(_class.fullName, "char *"))     // TESTING THIS WITH NEW String class...
1977                         // TESTING WITHOUT THE ABOVE NOW!
1978                         {
1979                            Expression checkedExp;
1980                            Expression parentExp;
1981                            Expression newExp;
1982
1983                            checkedExp = e;
1984                            parentExp = exp;
1985                            while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
1986                            {
1987                               parentExp = checkedExp;
1988                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
1989                               {
1990                                  if(checkedExp.type == extensionCompoundExp)
1991                                  {
1992                                     checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
1993                                  }
1994                                  else
1995                                     checkedExp = checkedExp.list->last;
1996                               }
1997                               else if(checkedExp.type == castExp)
1998                                  checkedExp = checkedExp.cast.exp;
1999                            }
2000
2001                            if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
2002                            {
2003                               /*
2004                               Expression newExp = e.op.exp2;
2005                               exp.call.arguments->Insert(e.prev, newExp);
2006                               exp.call.arguments->Remove(e);
2007                               e.op.exp2 = null;
2008                               FreeExpContents(e);
2009                               e = newExp;
2010                               */
2011                               newExp = checkedExp.op.exp2;
2012                               checkedExp.op.exp2 = null;
2013                               FreeExpContents(checkedExp);
2014                               
2015                               if(e.expType && e.expType.passAsTemplate)
2016                               {
2017                                  char size[100];
2018                                  ComputeTypeSize(e.expType);
2019                                  sprintf(size, "%d", e.expType.size);
2020                                  newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
2021                                     MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
2022                                        MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
2023                               }
2024
2025                               if(parentExp.type == callExp)
2026                               {                              
2027                                  exp.call.arguments->Insert(e.prev, newExp);
2028                                  exp.call.arguments->Remove(e);
2029                                  e = newExp;
2030                               }
2031                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
2032                               {
2033                                  parentExp.list->Remove(checkedExp);
2034                                  parentExp.list->Add(newExp);
2035                               }
2036                               else if(parentExp.type == castExp)
2037                               {
2038                                  // NEW CODE: BETTER WAY TO DO THIS? To prevent (double)(double *)
2039                                  if(parentExp.destType && parentExp.destType.kind == ellipsisType)
2040                                  {
2041                                     FreeTypeName(parentExp.cast.typeName);
2042                                     parentExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null));
2043                                  }
2044                                  parentExp.cast.exp = newExp;
2045                               }
2046                               else if(parentExp.type == extensionCompoundExp)
2047                               {
2048                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2049                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2050                               }
2051                               e.byReference = true;
2052
2053                               FreeType(checkedExp.expType);
2054                               FreeType(checkedExp.destType);
2055                               delete checkedExp;
2056                            }
2057                            else if((!e.byReference && (!e.expType || !e.expType.classObjectType) ) || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
2058                            {
2059                               Expression checkedExp;
2060                               Expression parentExp;
2061                               Expression newExp;
2062
2063                               {
2064                                  // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
2065                                  bool hasAddress =
2066                                     e.type == identifierExp ||
2067                                     (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
2068                                     (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
2069                                     (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
2070                                     e.type == indexExp;
2071
2072                                  if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
2073                                  {
2074                                     Context context = PushContext();
2075                                     Declarator decl;
2076                                     OldList * specs = MkList();
2077                                     char typeString[1024];
2078                                     Expression newExp { };
2079
2080                                     typeString[0] = '\0';
2081                                     *newExp = *e;
2082
2083                                     // TOCHECK: Should this read e.destType ???
2084
2085                                     if(exp.destType) exp.destType.refCount++;
2086                                     // if(exp.expType) exp.expType.refCount++;
2087                                     newExp.prev = null;
2088                                     newExp.next = null;
2089                                     newExp.expType = null;
2090
2091                                     PrintTypeNoConst(e.expType, typeString, false, true);
2092                                     decl = SpecDeclFromString(typeString, specs, null);
2093                                     newExp.destType = ProcessType(specs, decl);
2094
2095                                     curContext = context;
2096                                     e.type = extensionCompoundExp;
2097
2098                                     // We need a current compound for this
2099                                     if(curCompound)
2100                                     {
2101                                        char name[100];
2102                                        OldList * stmts = MkList();
2103                                        sprintf(name, "__internalValue%03X", internalValueCounter++);
2104                                        if(!curCompound.compound.declarations)
2105                                           curCompound.compound.declarations = MkList();
2106                                        curCompound.compound.declarations->Insert(null, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null))));
2107                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', newExp))));
2108                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier(name)))));
2109                                        e.compound = MkCompoundStmt(null, stmts);
2110                                     }
2111                                     else
2112                                        printf("libec: compiler error, curCompound is null in ApplyAnyObjectLogic\n");
2113
2114                                     /*
2115
2116                                     e.compound = MkCompoundStmt(
2117                                        MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))), 
2118                                        MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
2119                                     */
2120                                     
2121                                     e.compound.compound.context = context;
2122                                     PopContext(context);
2123                                     curContext = context.parent;
2124                                  }
2125                               }
2126
2127                               // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
2128                               checkedExp = e;
2129                               parentExp = exp;
2130                               while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
2131                               {
2132                                  parentExp = checkedExp;
2133                                  if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
2134                                  {
2135                                     if(checkedExp.type == extensionCompoundExp)
2136                                     {
2137                                        checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
2138                                     }
2139                                     else
2140                                        checkedExp = checkedExp.list->last;
2141                                  }
2142                                  else if(checkedExp.type == castExp)
2143                                     checkedExp = checkedExp.cast.exp;
2144                               }
2145                               newExp = MkExpOp(null, '&', checkedExp);
2146                               newExp.byReference = true;
2147                               if(parentExp.type == callExp)
2148                               {                              
2149                                  exp.call.arguments->Insert(e.prev, newExp);
2150                                  exp.call.arguments->Remove(e);
2151                                  e = newExp;
2152                               }
2153                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
2154                               {
2155                                  parentExp.list->Remove(checkedExp);
2156                                  parentExp.list->Add(newExp);
2157                               }
2158                               else if(parentExp.type == castExp)
2159                                  parentExp.cast.exp = newExp;
2160                               else if(parentExp.type == bracketsExp || parentExp.type == extensionCompoundExp)
2161                               {
2162                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2163                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2164                               }
2165                            }
2166                         }
2167                      }
2168                      
2169                      if(destType.classObjectType == ClassObjectType::typedObject)
2170                      {
2171                         char className[1024];
2172                         // Need the class itself here...
2173                         if(!_class && type.kind == pointerType && type.type && type.type.kind == charType)
2174                            _class = eSystem_FindClass(privateModule, "String");
2175                         if(!_class) _class = eSystem_FindClass(privateModule, "int");
2176
2177                         if(!strcmp(_class.name, "class"))
2178                         {
2179                            // Already inside a typed_object function, pass the class through
2180                            strcpy(className, "class");
2181                         }
2182                         else
2183                         {
2184                            strcpy(className, "__ecereClass_");
2185                            FullClassNameCat(className, _class.fullName, true);
2186                            MangleClassName(className);
2187
2188                            if(!_class.symbol)
2189                               _class.symbol = FindClass(_class.fullName);
2190
2191                            DeclareClass(_class.symbol, className);
2192                         }
2193                         exp.call.arguments->Insert(e.prev, MkExpIdentifier(MkIdentifier(className)));
2194                      }
2195                   }
2196                }
2197                {
2198 #ifdef _DEBUG
2199                   //char debugString[4096] = "";
2200                   //PrintExpression(e, debugString);
2201 #endif
2202                   // If expression type is a simple class, make it an address
2203                   FixReference(e, true);
2204                }
2205             }
2206             if(ellipsisDestType)
2207             {
2208                if(usedEllipsis || 
2209                   (exp.call.exp.expType && exp.call.exp.expType.kind == functionType && exp.call.exp.expType.params.last && 
2210                    ((Type)exp.call.exp.expType.params.last).kind == ellipsisType))
2211                {
2212                   exp.call.arguments->Insert(exp.call.arguments->last, MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null),null)),MkExpConstant("0")));
2213                }
2214             }
2215          }
2216          break;
2217       }
2218       case memberExp:
2219       {
2220          bool changeToPtr = false;
2221          bool noHead = false;
2222          Type type = exp.member.exp.expType;
2223          Specifier memberClassSpecifier = exp.member.member ? exp.member.member._class : null;
2224          if(exp.member.member) exp.member.member._class = null;
2225
2226          if(type && type.kind == templateType)
2227          {
2228             Type baseType = ProcessTemplateParameterType(type.templateParameter);
2229             if(baseType) type = baseType;
2230          }
2231          if(type && exp.member.member && !type.directClassAccess)
2232          {
2233             Class _class = exp.member.member.classSym ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
2234             Property prop = null;
2235             ClassProperty classProperty = null;
2236             Method method = null;
2237             Class convertTo = null;
2238             DataMember member = null;
2239             bool thisPtr = exp.member.thisPtr;
2240             if(type.kind == subClassType && exp.member.exp.type == classExp)
2241                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
2242
2243             // TEST: exp.member.exp.tempCount = Max(exp.tempCount, exp.member.exp.tempCount);
2244
2245             if(!_class)
2246             {
2247                // DANGER: Buffer overflow
2248                char string[2048] = "";
2249                Symbol classSym;
2250                PrintTypeNoConst(type, string, false, true);
2251                classSym = FindClass(string);
2252                _class = classSym ? classSym.registered : null;
2253             }
2254
2255             if(_class && exp.member.memberType == dataMember)
2256             {
2257                if(!thisPtr && !exp.member.member.classSym)
2258                   member = eClass_FindDataMember(_class, exp.member.member.string, null, null, null);
2259                if(!member)
2260                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
2261             }
2262             else if(_class && exp.member.memberType == propertyMember)
2263             {
2264                if(!thisPtr && !exp.member.member.classSym)
2265                   prop = eClass_FindProperty(_class, exp.member.member.string, null);
2266                if(!prop)
2267                   prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
2268                if(prop && (exp.usage.usageRef || 
2269                   (exp.usage.usageGet && !prop.Get && !prop.conversion) ||
2270                   (exp.usage.usageDelete && !prop.Set && !prop.conversion)))
2271                {
2272                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
2273                   if(member)
2274                   {
2275                      exp.member.memberType = dataMember;
2276                      prop = null;
2277                   }
2278                   else 
2279                   {
2280                      if(exp.usage.usageRef)
2281                         Compiler_Error($"cannot obtain address of property\n");
2282                      else if(!prop.Get)
2283                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2284                      else if(exp.usage.usageDelete)
2285                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2286                   }
2287                }
2288             }
2289             else if(_class && exp.member.memberType == methodMember)
2290             {
2291                if(!thisPtr)
2292                   method = eClass_FindMethod(_class, exp.member.member.string, null);
2293                if(!method)
2294                   method = eClass_FindMethod(_class, exp.member.member.string, privateModule);
2295             }
2296             else if(_class && exp.member.memberType == reverseConversionMember)
2297             {
2298                convertTo = _class;
2299                _class = FindClass(exp.member.member.string).registered;
2300                // prop = eClass_FindProperty(_class, convertTo.name, privateModule);
2301                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
2302             }
2303             else if(_class && exp.member.memberType == classPropertyMember)
2304             {
2305                classProperty = eClass_FindClassProperty(_class, exp.member.member.string);
2306             }
2307             if(prop)
2308             {
2309                // Only process Gets here, Set is processed in opExp's '='
2310                if(exp.usage.usageGet)
2311                {
2312                   if(prop.Get)
2313                   {
2314                      char getName[1024], setName[1024];
2315                      Expression ptr = exp.member.exp;
2316                      Class propertyClass;
2317                      char * nameToUse = convertTo ? setName : getName;
2318
2319                      FreeIdentifier(exp.member.member);
2320
2321                      // Process this here since it won't be processed at the end...
2322                      exp.member.exp.usage.usageGet = true;
2323                      ProcessExpression(exp.member.exp);
2324                      // TEST: exp.tempCount = exp.member.exp.tempCount;
2325
2326                      DeclareProperty(prop, setName, getName);
2327                      //propertyClass = convertTo ? _class : ((Symbol)prop.symbol)._class;
2328                      propertyClass = convertTo ? _class : 
2329                         ((((Symbol)prop.symbol).type && ((Symbol)prop.symbol).type.kind == classType) ? ((Symbol)prop.symbol).type._class.registered : ((Symbol)prop.symbol)._class);
2330
2331
2332                      if(propertyClass && propertyClass.type == bitClass)
2333                      {
2334                         // Bit classes shouldn't have properties except for conversions...
2335                         OldList * args = MkList();
2336                         if(exp.usage.usageDeepGet)
2337                         {
2338                            char className[1024];
2339                            Declaration decl;
2340                            Declarator declarator;
2341                            OldList * specs = MkList(), * decls = MkList();
2342                            Expression tempExp;
2343
2344                            // Make a declaration in the closest compound statement
2345                            // (Do not reuse (since using address for function calls)...)
2346                            sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2347                            declarator = 
2348                               SpecDeclFromString(propertyClass.dataTypeString, specs, 
2349                                  MkDeclaratorIdentifier(MkIdentifier(className)));
2350
2351                            ListAdd(decls, MkInitDeclarator(declarator, null));
2352
2353                            decl = MkDeclaration(specs, decls);
2354                            if(!curCompound.compound.declarations)
2355                               curCompound.compound.declarations = MkList();
2356                            curCompound.compound.declarations->Insert(null, decl);
2357
2358                            tempExp = QMkExpId(className);
2359                            tempExp.expType = MkClassType(propertyClass.fullName);
2360
2361                            exp.op.exp1 = tempExp;
2362                            exp.op.exp2 = MkExpCall(QMkExpId(nameToUse), args);
2363                            exp.op.op = '=';
2364                            exp.type = opExp;
2365                         }
2366                         else
2367                         {
2368                            exp.type = callExp;
2369                            exp.call.exp = QMkExpId(nameToUse);
2370                            exp.call.arguments = args;
2371                         }
2372                         ListAdd(args, FixReference(ptr, true));
2373                      }
2374                      else if(propertyClass && propertyClass.type == unitClass)
2375                      {
2376                         OldList * args = MkList();
2377                         ListAdd(args, FixReference(ptr, true));
2378                         exp.type = callExp;
2379                         exp.call.exp = QMkExpId(nameToUse);
2380                         exp.call.arguments = args;
2381                      }
2382                      else if(propertyClass && propertyClass.type == structClass)
2383                      {
2384                         OldList * args = MkList();
2385                         char className[1024];
2386                         Declaration decl;
2387                         OldList * specs = MkList(), * decls = MkList();
2388                         Expression tempExp;
2389
2390                         // Make a declaration in the closest compound statement
2391                         // (Do not reuse (since using address for function calls)...)
2392
2393                         className[0] = 0;
2394                         FullClassNameCat(className, propertyClass.fullName, false); //true);
2395
2396                         //ListAdd(specs, MkSpecifierName(className));
2397                         ListAdd(specs, MkStructOrUnion(structSpecifier, MkIdentifier(className), null));
2398
2399                         sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2400
2401                         ListAdd(decls, MkInitDeclarator(
2402                            MkDeclaratorIdentifier(MkIdentifier(className)), null));
2403
2404                         decl = MkDeclaration(specs, decls);
2405                         if(curCompound)
2406                         {
2407                            if(!curCompound.compound.declarations)
2408                               curCompound.compound.declarations = MkList();
2409                            curCompound.compound.declarations->Insert(null, decl);
2410                         }
2411
2412                         tempExp = QMkExpId(className);
2413                         tempExp.expType = MkClassType(propertyClass.fullName);
2414
2415                         if(convertTo)
2416                         {
2417                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2418                            ListAdd(args, FixReference(ptr, true));
2419                         }
2420                         else
2421                         {
2422                            ListAdd(args, FixReference(ptr, true));
2423                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2424                         }
2425
2426                         if(exp.usage.usageDeepGet)
2427                         {
2428                            exp.type = callExp;
2429                            exp.call.exp = QMkExpId(nameToUse);
2430                            exp.call.arguments = args;
2431
2432                            FreeExpression(tempExp);
2433                         }
2434                         else
2435                         {
2436                            exp.type = bracketsExp;
2437                            exp.list = MkList();
2438                            ListAdd(exp.list, MkExpCall(QMkExpId(nameToUse),args));
2439                            if(exp.usage.usageMember)
2440                            {
2441                               ListAdd(exp.list, FixReference(tempExp, true));
2442                               exp.byReference = true;
2443                            }
2444                            else
2445                               ListAdd(exp.list, tempExp);
2446                         }
2447                      }
2448                      else
2449                      {
2450                         exp.type = callExp;
2451                         exp.call.exp = QMkExpId(nameToUse);
2452                         exp.call.arguments = MkList();
2453                         ListAdd(exp.call.arguments, FixReference(ptr, true));
2454                      }
2455                   }
2456                   else if(prop.conversion)
2457                   {
2458                      void * prev = exp.prev, * next = exp.next;
2459                      *exp = *exp.member.exp;
2460                      exp.prev = prev;
2461                      exp.next = next;
2462                   }
2463                }
2464             }
2465             else if(classProperty)
2466             {
2467                // Only process Gets here, Set is processed in opExp's '='
2468                if(exp.usage.usageGet)
2469                {
2470                   if(classProperty.Get)
2471                   {
2472                      Identifier id = exp.member.member;
2473                      Expression classExp = exp.member.exp;
2474
2475                      // Class Property
2476                      exp.type = callExp;
2477                      exp.call.exp = MkExpIdentifier(MkIdentifier("ecere::com::eClass_GetProperty"));
2478                      exp.call.arguments = MkList();
2479                      ListAdd(exp.call.arguments, classExp);
2480                      ListAdd(exp.call.arguments, MkExpString(QMkString(id.string)));
2481                      FreeIdentifier(id);
2482
2483                      ProcessExpression(exp);
2484                      return;
2485                   }
2486                }
2487             }
2488             else if(method)
2489             {
2490                // Get the function address if it's not called
2491                if((exp.usage.usageGet || exp.member.exp.expType.kind == subClassType) && !(exp.usage.usageCall))
2492                {
2493                   char name[1024];
2494
2495                   FreeIdentifier(exp.member.member);
2496
2497                   // Process this here since it won't be processed at the end...
2498                   exp.member.exp.usage.usageGet = true;
2499                   ProcessExpression(exp.member.exp);
2500                   // TEST: exp.tempCount = exp.member.exp.tempCount;
2501
2502                   if(method.type == virtualMethod)
2503                   {
2504                      strcpy(name, "__ecereVMethodID_");
2505                      FullClassNameCat(name, method._class.fullName, false);
2506                      strcat(name, "_");
2507                      strcat(name, method.name);
2508                      exp.type = indexExp;
2509                      if(memberClassSpecifier)
2510                      {
2511                         char className[1024];
2512                         // Need the class itself here...
2513                         strcpy(className, "__ecereClass_");
2514                         FullClassNameCat(className, _class.fullName, true);
2515                         MangleClassName(className);
2516
2517                         if(!_class.symbol)
2518                            _class.symbol = FindClass(_class.fullName);
2519                         DeclareClass(_class.symbol, className);
2520                         exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl"));
2521
2522                         // WHAT HAPPENS TO exp.member.exp ?
2523                      }
2524                      else
2525                      {
2526                         if(exp.thisPtr && _class.type != normalClass)
2527                         {
2528                            FreeExpression(exp.member.exp);
2529                            exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("_vTbl"));
2530                         }
2531                         else
2532                            exp.index.exp = MkExpPointer(exp.member.exp, MkIdentifier("_vTbl"));
2533                      }
2534                      exp.index.index = MkListOne(QMkExpId(name));
2535                      DeclareMethod(method, name);
2536                   }
2537                   else
2538                   {
2539                      FreeExpression(exp.member.exp);
2540                      exp.type = identifierExp;
2541                      strcpy(name, "__ecereMethod_");
2542                      FullClassNameCat(name, method._class.fullName, false);
2543                      strcat(name, "_");
2544                      strcat(name, method.name);
2545                      exp.identifier = MkIdentifier(name);
2546                      DeclareMethod(method, name);
2547                   }
2548                }
2549             }
2550             else if(member)
2551             {
2552                // Process this here since it won't be processed at the end...
2553                if(exp.usage.usageGet)
2554                {
2555                   exp.member.exp.usage.usageGet = true;   // Recently added this... is it ok?
2556                }
2557                ProcessExpression(exp.member.exp);
2558                // TEST: exp.tempCount = exp.member.exp.tempCount;
2559
2560                if(type.kind == classType)
2561                   DeclareStruct(type._class.registered.fullName, false);
2562
2563                // TESTING THIS NOHEAD STUFF...
2564                if(_class.type == noHeadClass)
2565                {
2566                   noHead = true;
2567                }
2568                else if(_class.type == structClass)
2569                {
2570                   changeToPtr = true;
2571                }
2572                else if(_class.type == bitClass)
2573                {
2574                   OldList * list = MkList();
2575                   char mask[32], shift[10];
2576                   OldList * specs = MkList();
2577                   BitMember bitMember = (BitMember) member;
2578                   Declarator decl = SpecDeclFromString(bitMember.dataTypeString, specs, null);
2579                   TypeName type = MkTypeName(specs, decl);
2580                   if(bitMember.mask > MAXDWORD)
2581                      sprintf(mask, FORMAT64HEXLL, bitMember.mask);
2582                   else
2583                      sprintf(mask, FORMAT64HEX, bitMember.mask);
2584                   sprintf(shift, "%d", bitMember.pos);
2585                   
2586                   FreeIdentifier(exp.member.member);
2587                  
2588                   // ((type) ((color & mask) >> bitPos))
2589                   ListAdd(list, MkExpCast(type, MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(MkListOne(
2590                      MkExpOp(exp.member.exp, '&', MkExpConstant(mask)))), RIGHT_OP, 
2591                         MkExpConstant(shift))))));
2592
2593                   exp.type = bracketsExp;
2594                   exp.list = list;
2595                }
2596                else if(_class.type == unitClass)
2597                {
2598                }
2599                else
2600                {
2601                   // If it's a this pointer, replace by precomputed shortcut
2602                   if(thisPtr)
2603                   {
2604                      char pointerName[1024];
2605
2606                      strcpy(pointerName, "__ecerePointer_");
2607                      FullClassNameCat(pointerName, type._class.registered.fullName, false);
2608                      FreeIdentifier(exp.member.exp.identifier);
2609                      exp.member.exp.identifier = MkIdentifier(pointerName);
2610                   }
2611                   // Otherwise, access the data the hard way
2612                   else
2613                   {
2614                      Expression bytePtr, e;
2615                      Expression classExp;
2616                      Expression checkedExp;
2617                      char structName[1024];
2618                      char className[1024];
2619                      strcpy(className, "__ecereClass_");
2620                      FullClassNameCat(className, member._class.fullName, true);
2621                      MangleClassName(className);
2622
2623                      // classExp = QMkExpId(className);
2624
2625                      if(!member._class.symbol)
2626                         member._class.symbol = FindClass(member._class.fullName);
2627
2628                      DeclareClass(member._class.symbol, className);
2629                      DeclareStruct(member._class.fullName, false);
2630
2631                      structName[0] = 0;
2632                      FullClassNameCat(structName, member._class.fullName, false);
2633
2634                      checkedExp = exp.member.exp;
2635                      while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list && checkedExp.list->count == 1) ||
2636                            checkedExp.type == castExp)
2637                      {
2638                         if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
2639                            checkedExp = checkedExp.list->last;
2640                         else if(checkedExp.type == castExp)
2641                            checkedExp = checkedExp.cast.exp;
2642                      }
2643
2644                      if(checkedExp.type != identifierExp &&
2645                         checkedExp.type != constantExp &&      // Added this here... Might mess up if we need address?
2646                         checkedExp.type != memberExp && checkedExp.type != pointerExp)
2647                      {
2648                         char ecereTemp[100];
2649                         Statement compound;
2650                         OldList * list = MkList();
2651                         Context context = PushContext();
2652                         if(exp.member.exp.tempCount > exp.tempCount)
2653                            exp.tempCount = exp.member.exp.tempCount;
2654
2655                         exp.tempCount++;
2656                         curExternal.function.tempCount = Max(curExternal.function.tempCount, exp.tempCount);
2657                         sprintf(ecereTemp, "__ecTemp%d", exp.tempCount);
2658                         curContext = context;
2659                         compound = MkCompoundStmt(
2660                            MkListOne(MkDeclaration(MkListOne(MkSpecifier(CHAR)), MkListOne(MkInitDeclarator(
2661                               MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier(ecereTemp))),
2662                                  MkInitializerAssignment(QBrackets(exp.member.exp)))))), null);
2663                         if(member._class.fixed)
2664                         {
2665                            if(member._class.templateClass ? member._class.templateClass.offset : member._class.offset)
2666                            {
2667                               char string[256];
2668                               sprintf(string, "%d", member._class.templateClass ? member._class.templateClass.offset : member._class.offset);
2669                               e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', MkExpConstant(string)));
2670                            }
2671                            else
2672                               e = QMkExpId(ecereTemp);
2673                         }
2674                         else
2675                         {
2676                            e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', 
2677                               MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
2678                         }
2679
2680                         compound.compound.context = context;
2681                         compound.compound.statements = MkListOne(MkExpressionStmt(MkListOne(
2682                            QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), 
2683                               MkDeclaratorPointer(MkPointer(null, null), null)), e)))));
2684
2685                         exp.member.exp =  MkExpExtensionCompound(compound);
2686
2687                         PopContext(context);
2688                         curContext = context.parent;
2689                      }
2690                      else
2691                      {
2692                         bytePtr = MkExpCast(QMkType("char", QMkPtrDecl(null)), /*CopyExpression(*/exp.member.exp/*)*/);
2693                         // DISABLED BECAUSE PREVENTS GETTING ADDRESS OF MEMBERS WITH ADDRESS 0
2694                         /*
2695                         e = QBrackets(QMkExpCond(exp.member.exp, 
2696                            QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(classExp, MkIdentifier("offset")))),
2697                            MkExpConstant("0")));
2698                         */
2699                         
2700                         // if(class.fixed)
2701                         if(member._class.fixed)
2702                         {
2703                            if(member._class.templateClass ? member._class.templateClass.offset : member._class.offset)
2704                            {
2705                               char string[256];
2706                               sprintf(string, "%d", member._class.templateClass ? member._class.templateClass.offset : member._class.offset);
2707                               e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string))));
2708                            }
2709                            else
2710                               e = bytePtr;
2711                         }
2712                         else
2713                            e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(QMkExpId(className), MkIdentifier("offset")))));
2714
2715                         // exp.member.exp = QBrackets(MkExpCast(QMkType(structName, QMkPtrDecl(null)), e));
2716                         exp.member.exp = QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), QMkPtrDecl(null)), e));
2717                      }
2718                   }
2719                   exp.type = pointerExp;
2720                }
2721             }
2722          }
2723
2724          // Take Out Any Class Specifier (Should have been used by now)
2725          FreeSpecifier(memberClassSpecifier);
2726
2727          // Just moved this at the end... How is it?
2728          if(exp.type == memberExp || exp.type == pointerExp)
2729          {
2730             exp.member.exp.usage.usageGet = true;
2731             exp.member.exp.usage.usageMember = true;
2732             exp.member.exp.tempCount = exp.tempCount;
2733             ProcessExpression(exp.member.exp);
2734             exp.tempCount = exp.member.exp.tempCount;
2735             if((changeToPtr && exp.member.exp.byReference) || noHead)
2736                exp.type = pointerExp;
2737          }
2738          break;
2739       }
2740       case extensionCompoundExp:
2741       {
2742          Expression e = ((Statement)exp.compound.compound.statements->last).expressions->last;
2743          if(e)
2744             e.usage |= exp.usage & ExpUsage { usageGet = true, usageArg = true, usageMember = true };
2745
2746          ProcessStatement(exp.compound);
2747
2748          /*if(((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference)
2749             exp.byReference = ((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference;*/
2750          break;
2751       }
2752       case pointerExp:
2753       {
2754          exp.member.exp.usage.usageGet = true;
2755          ProcessExpression(exp.member.exp);
2756          break;
2757       }
2758       case typeSizeExp:
2759       {
2760          Specifier spec = exp.typeName.qualifiers ? exp.typeName.qualifiers->first : null;
2761          if(spec && spec.type == templateTypeSpecifier && !exp.typeName.declarator)
2762          {
2763             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, false);
2764             if(argExp)
2765             {
2766                Expression classExp;
2767                
2768                FreeTypeName(exp.typeName);
2769
2770                classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
2771
2772                exp.type = bracketsExp;
2773                exp.list = MkListOne(
2774                   MkExpCondition(MkExpBrackets(MkListOne(
2775                      MkExpOp(
2776                         MkExpOp(
2777                            MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, 
2778                               MkExpIdentifier(MkIdentifier("normalClass"))), 
2779                         OR_OP,
2780                         MkExpOp(
2781                            MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, 
2782                               MkExpIdentifier(MkIdentifier("noHeadClass"))
2783                             )))),
2784                      MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)))),
2785                      MkExpMember(classExp, MkIdentifier("typeSize")))
2786                   ); 
2787
2788                ProcessExpressionType(exp);
2789                ProcessExpression(exp);
2790             }
2791          }
2792          break;
2793       }
2794       case castExp:
2795       {
2796          if(exp.cast.exp)
2797          {
2798             exp.cast.exp.usage |= exp.usage & ExpUsage { usageGet = true, usageMember = true };
2799             ProcessExpression(exp.cast.exp);
2800             // TESTING THIS
2801             if(exp.cast.exp.byReference)
2802                exp.byReference = exp.cast.exp.byReference;
2803             if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass &&
2804                exp.cast.exp.expType && (exp.cast.exp.expType.kind == pointerType || exp.cast.exp.expType.kind == arrayType || (
2805                   exp.cast.exp.expType.kind == classType && exp.cast.exp.expType._class && exp.cast.exp.expType._class.registered && 
2806                      !strcmp(exp.cast.exp.expType._class.registered.dataTypeString, "char *")) ) )
2807                exp.byReference = true;
2808          }
2809          // Moved this to 1.5...
2810          //exp.expType = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
2811          break;
2812       }
2813       case conditionExp:
2814       {
2815          Expression e;
2816          if(exp.usage.usageGet)
2817             exp.cond.cond.usage.usageGet = true;
2818          ProcessExpression(exp.cond.cond);
2819          for(e = exp.cond.exp->first; e; e = e.next)
2820          {
2821             if(!e.next && exp.usage.usageGet) e.usage.usageGet = true;
2822             ProcessExpression(e);
2823          }
2824          if(exp.usage.usageGet)
2825             exp.cond.elseExp.usage.usageGet = true;
2826          ProcessExpression(exp.cond.elseExp);
2827          break;
2828       }
2829       case classExp:
2830       {
2831          // Need the class itself here...
2832          if(exp._classExp.specifiers && exp._classExp.specifiers->first && ((Specifier)exp._classExp.specifiers->first).type == templateTypeSpecifier)
2833          {
2834             Specifier spec = exp._classExp.specifiers->first;
2835             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, true);
2836             if(argExp)
2837             {
2838                FreeList(exp._classExp.specifiers, FreeSpecifier);
2839                if(exp._classExp.decl)
2840                   FreeDeclarator(exp._classExp.decl);
2841
2842                exp.type = memberExp; //pointerExp;
2843                exp.member.exp = argExp;
2844                exp.member.member = MkIdentifier("dataTypeClass");
2845
2846                ProcessExpressionType(argExp);
2847                ProcessExpression(exp);
2848             }
2849          }
2850          else
2851          {
2852             char className[1024];
2853             char * string = StringFromSpecDecl(exp._classExp.specifiers, exp._classExp.decl);
2854             
2855             strcpy(className, "__ecereClass_");
2856             FullClassNameCat(className, string, true);      // TODO: Verify this
2857             MangleClassName(className);
2858             DeclareClass(FindClass(string), className);
2859             delete string;
2860
2861             FreeList(exp._classExp.specifiers, FreeSpecifier);
2862             if(exp._classExp.decl)
2863                FreeDeclarator(exp._classExp.decl);
2864
2865             exp.type = identifierExp;
2866             exp.identifier = MkIdentifier(className);
2867          }
2868          break;
2869       }
2870       case vaArgExp:
2871       {
2872          ProcessExpression(exp.vaArg.exp);
2873          break;
2874       }
2875       case extensionInitializerExp:
2876       {
2877          ProcessInitializer(exp.initializer.initializer);
2878          break;
2879       }
2880    }
2881    FixRefExp(exp);
2882    yylloc = oldyylloc;
2883 }
2884
2885 static void ProcessInitializer(Initializer init)
2886 {
2887    switch(init.type)
2888    {
2889       case expInitializer:
2890          init.exp.usage.usageGet = true;
2891          ProcessExpression(init.exp);
2892          if(init.exp.destType && init.exp.destType.kind == classType && init.exp.destType._class &&
2893             init.exp.destType._class.registered && init.exp.destType._class.registered.type == noHeadClass)
2894          {
2895             FixReference(init.exp, true);
2896          }
2897          else if(init.exp.destType && init.exp.destType.kind == classType)
2898             FixReference(init.exp, false);
2899          break;
2900       case listInitializer:
2901       {
2902          Initializer i;
2903          for(i = init.list->first; i; i = i.next)
2904             ProcessInitializer(i);
2905          break;
2906       }
2907    }
2908 }
2909
2910 static void ProcessDeclaration(Declaration decl)
2911 {
2912    switch(decl.type)
2913    {
2914       case initDeclaration:
2915       {
2916          if(decl.declarators)
2917          {
2918             InitDeclarator d;
2919          
2920             for(d = decl.declarators->first; d; d = d.next)
2921             {
2922                if(d.initializer)
2923                   ProcessInitializer(d.initializer);
2924             }
2925          }
2926          break;
2927       }
2928    }
2929 }
2930
2931 static void ProcessStatement(Statement stmt)
2932 {
2933    switch(stmt.type)
2934    {
2935       case labeledStmt:
2936          ProcessStatement(stmt.labeled.stmt);
2937          break;
2938       case caseStmt:
2939          if(stmt.caseStmt.exp)
2940          {
2941             stmt.caseStmt.exp.usage.usageGet = true;
2942
2943             // This expression should be constant...
2944             ProcessExpression(stmt.caseStmt.exp);
2945          }
2946          if(stmt.caseStmt.stmt)
2947             ProcessStatement(stmt.caseStmt.stmt);
2948          break;
2949       case compoundStmt:
2950       {
2951          if(stmt.compound.context)
2952          {
2953             Declaration decl;
2954             Statement s;
2955             Statement prevCompound = curCompound;
2956             Context prevContext = curContext;
2957
2958             if(!stmt.compound.isSwitch)
2959             {
2960                curCompound = stmt;
2961                curContext = stmt.compound.context;
2962             }
2963
2964             if(stmt.compound.declarations)
2965             {
2966                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
2967                   ProcessDeclaration(decl);
2968             }
2969             if(stmt.compound.statements)
2970             {
2971                for(s = stmt.compound.statements->first; s; s = s.next)
2972                   ProcessStatement(s);
2973             }
2974             curContext = prevContext;
2975             curCompound = prevCompound;
2976          }
2977          break;
2978       }
2979       case expressionStmt:
2980       {
2981          Expression exp;
2982          if(stmt.expressions)
2983          {
2984             for(exp = stmt.expressions->first; exp; exp = exp.next)
2985             {
2986                ProcessExpression(exp);
2987             }
2988          }
2989          break;
2990       }
2991       case ifStmt:
2992       {
2993          if(stmt.ifStmt.exp)
2994          {
2995             Expression exp;
2996
2997             ((Expression)stmt.ifStmt.exp->last).usage.usageGet = true;
2998             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
2999             {
3000                ProcessExpression(exp);
3001             }
3002          }
3003          if(stmt.ifStmt.stmt)
3004             ProcessStatement(stmt.ifStmt.stmt);
3005          if(stmt.ifStmt.elseStmt)
3006             ProcessStatement(stmt.ifStmt.elseStmt);
3007          break;
3008       }
3009       case switchStmt:
3010       {
3011          Expression exp;
3012          ((Expression)stmt.switchStmt.exp->last).usage.usageGet = true;
3013          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
3014          {
3015             ProcessExpression(exp);
3016          }
3017          ProcessStatement(stmt.switchStmt.stmt);
3018          break;
3019       }
3020       case whileStmt:
3021       {
3022          Expression exp;
3023          ((Expression)stmt.whileStmt.exp->last).usage.usageGet = true;
3024          for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
3025          {
3026             ProcessExpression(exp);
3027          }
3028          ProcessStatement(stmt.whileStmt.stmt);
3029          break;
3030       }
3031       case doWhileStmt:
3032       {
3033          Expression exp;
3034          if(stmt.doWhile.exp && stmt.doWhile.exp->last)
3035          {
3036             ((Expression)stmt.doWhile.exp->last).usage.usageGet = true;
3037             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
3038             {
3039                ProcessExpression(exp);
3040             }
3041          }
3042          if(stmt.doWhile.stmt)
3043             ProcessStatement(stmt.doWhile.stmt);
3044          break;
3045       }
3046       case forStmt:
3047       {
3048          Expression exp;
3049          if(stmt.forStmt.init)
3050             ProcessStatement(stmt.forStmt.init);
3051
3052          if(stmt.forStmt.check)
3053          {
3054             if(stmt.forStmt.check.expressions)
3055             {
3056                ((Expression)stmt.forStmt.check.expressions->last).usage.usageGet = true;
3057             }
3058             ProcessStatement(stmt.forStmt.check);
3059          }
3060          if(stmt.forStmt.increment)
3061          {        
3062             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
3063             {
3064                ProcessExpression(exp);
3065             }
3066          }
3067          if(stmt.forStmt.stmt)
3068             ProcessStatement(stmt.forStmt.stmt);
3069          break;
3070       }
3071       case gotoStmt:
3072          break;
3073       case continueStmt:
3074          break;
3075       case breakStmt:
3076          break;
3077       case returnStmt:
3078       {
3079          Expression exp;
3080          if(stmt.expressions)
3081          {
3082             ((Expression)stmt.expressions->last).usage.usageGet = true;
3083             for(exp = stmt.expressions->first; exp; exp = exp.next)
3084             {
3085                ProcessExpression(exp);
3086                // TOCHECK: This was added 2013/02/09 as part of 64 bit port for structs in class properties to automatically be returned by reference
3087                if(!exp.next && exp.destType && exp.destType.byReference)
3088                   FixReference(exp, true);
3089             }
3090          }
3091          break;
3092       }
3093       case badDeclarationStmt:
3094       {
3095          ProcessDeclaration(stmt.decl);
3096          break;
3097       }
3098       case asmStmt:
3099       {
3100          AsmField field;
3101          if(stmt.asmStmt.inputFields)
3102          {
3103             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
3104                if(field.expression)
3105                   ProcessExpression(field.expression);
3106          }
3107          if(stmt.asmStmt.outputFields)
3108          {
3109             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
3110                if(field.expression)
3111                   ProcessExpression(field.expression);
3112          }
3113          if(stmt.asmStmt.clobberedFields)
3114          {
3115             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
3116                if(field.expression)
3117                   ProcessExpression(field.expression);
3118          }
3119          break;
3120       }
3121    }
3122 }
3123
3124 static void ProcessFunction(FunctionDefinition function)
3125 {
3126    if(function.body)
3127       ProcessStatement(function.body);
3128 }
3129
3130 static void ProcessMemberInitData(MemberInit member)
3131 {
3132    if(member.initializer)
3133       ProcessInitializer(member.initializer);
3134 }
3135
3136 static void ProcessInstantiation(Instantiation inst)
3137 {
3138    if(inst.members)
3139    {
3140       MembersInit members;
3141       for(members = inst.members->first; members; members = members.next)
3142       {
3143          if(members.type == dataMembersInit)
3144          {
3145             if(members.dataMembers)
3146             {
3147                MemberInit member;
3148                for(member = members.dataMembers->first; member; member = member.next)
3149                   ProcessMemberInitData(member);
3150             }
3151          }
3152          else if(members.type == methodMembersInit)
3153          {
3154             ProcessFunction((FunctionDefinition)members.function);
3155          }
3156       }
3157    }
3158 }
3159
3160 /////////// MEMBER ACCESS PASS /////////////////////////////////////////////
3161 public void ProcessMemberAccess()
3162 {
3163    External external;
3164    for(external = ast->first; external; external = external.next)
3165    {
3166       curExternal = external;
3167       // There shouldn't be any class member access here anyways...
3168       if(external.type == declarationExternal)
3169       {
3170          if(external.declaration)
3171             ProcessDeclaration(external.declaration);
3172       }
3173    }
3174    
3175    for(external = ast->first; external; external = external.next)
3176    {
3177       curExternal = external;
3178       if(external.type == functionExternal)
3179       {
3180          ProcessFunction(external.function);
3181       }
3182       else if(external.type == declarationExternal)
3183       {
3184          //currentClass = external.function._class;
3185          if(external.declaration)
3186             ProcessDeclaration(external.declaration);
3187       }
3188       else if(external.type == classExternal)
3189       {
3190          ClassDefinition _class = external._class;
3191          //currentClass = external.symbol.registered;
3192          if(_class.definitions)
3193          {
3194             ClassDef def;
3195             Class regClass = _class.symbol.registered;
3196
3197             // Process all functions
3198             for(def = _class.definitions->first; def; def = def.next)
3199             {
3200                if(def.type == functionClassDef)
3201                {
3202                   curExternal = def.function.declarator.symbol.pointerExternal;
3203                   ProcessFunction((FunctionDefinition)def.function);
3204                }
3205                else if(def.type == declarationClassDef && def.decl.type == instDeclaration)
3206                {
3207                   ProcessInstantiation(def.decl.inst);
3208                }
3209                else if(def.type == defaultPropertiesClassDef && def.defProperties)
3210                {
3211                   MemberInit defProperty;
3212
3213                   // Add this to the context
3214                   Symbol thisSymbol
3215                   {
3216                      string = CopyString("this");
3217                      type = MkClassType(regClass.fullName);
3218                   };
3219                   globalContext.symbols.Add((BTNode)thisSymbol);
3220                   
3221                   for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
3222                   {
3223                      //thisClass = regClass;
3224                      ProcessMemberInitData(defProperty); //, regClass, &id);
3225                      //thisClass = null;
3226                   }
3227
3228                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3229                   globalContext.symbols.Remove((BTNode)thisSymbol);
3230                   FreeSymbol(thisSymbol);
3231                }
3232                else if(def.type == propertyClassDef && def.propertyDef)
3233                {
3234                   PropertyDef prop = def.propertyDef;
3235
3236                   // Add this to the context
3237                   Symbol thisSymbol
3238                   {
3239                      string = CopyString("this");
3240                      type = MkClassType(regClass.fullName);
3241                   };
3242                   globalContext.symbols.Add((BTNode)thisSymbol);
3243                   
3244                   //thisClass = regClass;
3245                   if(prop.setStmt)
3246                   {
3247                      curExternal = prop.symbol.externalSet;
3248                      ProcessStatement(prop.setStmt);
3249                   }
3250                   if(prop.getStmt)
3251                   {
3252                      curExternal = prop.symbol.externalGet;
3253                      ProcessStatement(prop.getStmt);
3254                   }
3255                   if(prop.issetStmt)
3256                   {
3257                      curExternal = prop.symbol.externalIsSet;
3258                      ProcessStatement(prop.issetStmt);
3259                   }
3260
3261                   //thisClass = null;
3262
3263                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3264                   globalContext.symbols.Remove((BTNode)thisSymbol);
3265                   FreeSymbol(thisSymbol);
3266                }
3267                else if(def.type == classPropertyClassDef && def.propertyDef)
3268                {
3269                   PropertyDef prop = def.propertyDef;
3270
3271                   //thisClass = regClass;
3272                   if(prop.setStmt)
3273                   {
3274                      curExternal = prop.symbol.externalSet;
3275                      ProcessStatement(prop.setStmt);
3276                   }
3277                   if(prop.getStmt)
3278                   {
3279                      curExternal = prop.symbol.externalGet;
3280                      ProcessStatement(prop.getStmt);
3281                   }
3282                   //thisClass = null;
3283                }
3284                else if(def.type == propertyWatchClassDef && def.propertyWatch)
3285                {
3286                   PropertyWatch propertyWatch = def.propertyWatch;
3287         
3288                   // Add this to the context
3289                   Symbol thisSymbol
3290                   {
3291                      string = CopyString("this");
3292                      type = MkClassType(regClass.fullName);
3293                   };
3294                   globalContext.symbols.Add((BTNode)thisSymbol);
3295                   
3296                   //thisClass = regClass;
3297                   if(propertyWatch.compound)
3298                   {
3299                      Symbol thisSymbol
3300                      {
3301                         string = CopyString("this");
3302                         type = MkClassType(regClass.fullName);
3303                      };
3304                      propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
3305                      curExternal = null;
3306                      ProcessStatement(propertyWatch.compound);
3307                   }
3308                   // thisClass = null;
3309
3310                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3311                   globalContext.symbols.Remove((BTNode)thisSymbol);
3312                   FreeSymbol(thisSymbol);
3313                }
3314             }
3315          }
3316       }
3317    }
3318 }