wip II
[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 && !type.declaredWithStruct) || _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 ? memberExp.member.exp.expType : null;
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(_class.type == normalClass && destType.byReference == false && strcmp(_class.dataTypeString, "char *"))
2178                         {
2179                            exp.call.arguments->Insert(e.prev, MkExpPointer(CopyExpression(e), MkIdentifier("_class")));
2180                         }
2181                         else
2182                         {
2183                            if(!strcmp(_class.name, "class"))
2184                            {
2185                               // Already inside a typed_object function, pass the class through
2186                               strcpy(className, "class");
2187                            }
2188                            else
2189                            {
2190                               strcpy(className, "__ecereClass_");
2191                               FullClassNameCat(className, _class.fullName, true);
2192                               MangleClassName(className);
2193
2194                               if(!_class.symbol)
2195                                  _class.symbol = FindClass(_class.fullName);
2196
2197                               DeclareClass(_class.symbol, className);
2198                            }
2199                            exp.call.arguments->Insert(e.prev, MkExpIdentifier(MkIdentifier(className)));
2200                         }
2201                      }
2202                   }
2203                }
2204                {
2205 #ifdef _DEBUG
2206                   //char debugString[4096] = "";
2207                   //PrintExpression(e, debugString);
2208 #endif
2209                   // If expression type is a simple class, make it an address
2210                   FixReference(e, !destType || !destType.declaredWithStruct);
2211                }
2212             }
2213             if(ellipsisDestType)
2214             {
2215                if(usedEllipsis || 
2216                   (exp.call.exp.expType && exp.call.exp.expType.kind == functionType && exp.call.exp.expType.params.last && 
2217                    ((Type)exp.call.exp.expType.params.last).kind == ellipsisType))
2218                {
2219                   exp.call.arguments->Insert(exp.call.arguments->last, MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null),null)),MkExpConstant("0")));
2220                }
2221             }
2222          }
2223          break;
2224       }
2225       case memberExp:
2226       {
2227          bool changeToPtr = false;
2228          bool noHead = false;
2229          Type type = exp.member.exp ? exp.member.exp.expType : null;
2230          Specifier memberClassSpecifier = exp.member.member ? exp.member.member._class : null;
2231          if(exp.member.member) exp.member.member._class = null;
2232
2233          if(type && type.kind == templateType)
2234          {
2235             Type baseType = ProcessTemplateParameterType(type.templateParameter);
2236             if(baseType) type = baseType;
2237          }
2238          if(type && exp.member.member && !type.directClassAccess)
2239          {
2240             Class _class = exp.member.member.classSym ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
2241             Property prop = null;
2242             ClassProperty classProperty = null;
2243             Method method = null;
2244             Class convertTo = null;
2245             DataMember member = null;
2246             bool thisPtr = exp.member.thisPtr;
2247             if(type.kind == subClassType && exp.member.exp.type == classExp)
2248                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
2249
2250             // TEST: exp.member.exp.tempCount = Max(exp.tempCount, exp.member.exp.tempCount);
2251
2252             if(!_class)
2253             {
2254                // DANGER: Buffer overflow
2255                char string[2048] = "";
2256                Symbol classSym;
2257                PrintTypeNoConst(type, string, false, true);
2258                classSym = FindClass(string);
2259                _class = classSym ? classSym.registered : null;
2260             }
2261
2262             if(_class && exp.member.memberType == dataMember)
2263             {
2264                if(!thisPtr && !exp.member.member.classSym)
2265                   member = eClass_FindDataMember(_class, exp.member.member.string, null, null, null);
2266                if(!member)
2267                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
2268             }
2269             else if(_class && exp.member.memberType == propertyMember)
2270             {
2271                if(!thisPtr && !exp.member.member.classSym)
2272                   prop = eClass_FindProperty(_class, exp.member.member.string, null);
2273                if(!prop)
2274                   prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
2275                if(prop && (exp.usage.usageRef || 
2276                   (exp.usage.usageGet && !prop.Get && !prop.conversion) ||
2277                   (exp.usage.usageDelete && !prop.Set && !prop.conversion)))
2278                {
2279                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
2280                   if(member)
2281                   {
2282                      exp.member.memberType = dataMember;
2283                      prop = null;
2284                   }
2285                   else 
2286                   {
2287                      if(exp.usage.usageRef)
2288                         Compiler_Error($"cannot obtain address of property\n");
2289                      else if(!prop.Get)
2290                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2291                      else if(exp.usage.usageDelete)
2292                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2293                   }
2294                }
2295             }
2296             else if(_class && exp.member.memberType == methodMember)
2297             {
2298                if(!thisPtr)
2299                   method = eClass_FindMethod(_class, exp.member.member.string, null);
2300                if(!method)
2301                   method = eClass_FindMethod(_class, exp.member.member.string, privateModule);
2302             }
2303             else if(_class && exp.member.memberType == reverseConversionMember)
2304             {
2305                convertTo = _class;
2306                _class = FindClass(exp.member.member.string).registered;
2307                // prop = eClass_FindProperty(_class, convertTo.name, privateModule);
2308                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
2309             }
2310             else if(_class && exp.member.memberType == classPropertyMember)
2311             {
2312                classProperty = eClass_FindClassProperty(_class, exp.member.member.string);
2313             }
2314             if(prop)
2315             {
2316                // Only process Gets here, Set is processed in opExp's '='
2317                if(exp.usage.usageGet)
2318                {
2319                   if(prop.Get)
2320                   {
2321                      char getName[1024], setName[1024];
2322                      Expression ptr = exp.member.exp;
2323                      Class propertyClass;
2324                      char * nameToUse = convertTo ? setName : getName;
2325
2326                      FreeIdentifier(exp.member.member);
2327
2328                      // Process this here since it won't be processed at the end...
2329                      exp.member.exp.usage.usageGet = true;
2330                      ProcessExpression(exp.member.exp);
2331                      // TEST: exp.tempCount = exp.member.exp.tempCount;
2332
2333                      DeclareProperty(prop, setName, getName);
2334                      //propertyClass = convertTo ? _class : ((Symbol)prop.symbol)._class;
2335                      propertyClass = convertTo ? _class : 
2336                         ((((Symbol)prop.symbol).type && ((Symbol)prop.symbol).type.kind == classType) ? ((Symbol)prop.symbol).type._class.registered : ((Symbol)prop.symbol)._class);
2337
2338
2339                      if(propertyClass && propertyClass.type == bitClass)
2340                      {
2341                         // Bit classes shouldn't have properties except for conversions...
2342                         OldList * args = MkList();
2343                         if(exp.usage.usageDeepGet)
2344                         {
2345                            char className[1024];
2346                            Declaration decl;
2347                            Declarator declarator;
2348                            OldList * specs = MkList(), * decls = MkList();
2349                            Expression tempExp;
2350
2351                            // Make a declaration in the closest compound statement
2352                            // (Do not reuse (since using address for function calls)...)
2353                            sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2354                            declarator = 
2355                               SpecDeclFromString(propertyClass.dataTypeString, specs, 
2356                                  MkDeclaratorIdentifier(MkIdentifier(className)));
2357
2358                            ListAdd(decls, MkInitDeclarator(declarator, null));
2359
2360                            decl = MkDeclaration(specs, decls);
2361                            if(!curCompound.compound.declarations)
2362                               curCompound.compound.declarations = MkList();
2363                            curCompound.compound.declarations->Insert(null, decl);
2364
2365                            tempExp = QMkExpId(className);
2366                            tempExp.expType = MkClassType(propertyClass.fullName);
2367
2368                            exp.op.exp1 = tempExp;
2369                            exp.op.exp2 = MkExpCall(QMkExpId(nameToUse), args);
2370                            exp.op.op = '=';
2371                            exp.type = opExp;
2372                         }
2373                         else
2374                         {
2375                            exp.type = callExp;
2376                            exp.call.exp = QMkExpId(nameToUse);
2377                            exp.call.arguments = args;
2378                         }
2379                         ListAdd(args, FixReference(ptr, true));
2380                      }
2381                      else if(propertyClass && propertyClass.type == unitClass)
2382                      {
2383                         OldList * args = MkList();
2384                         ListAdd(args, FixReference(ptr, true));
2385                         exp.type = callExp;
2386                         exp.call.exp = QMkExpId(nameToUse);
2387                         exp.call.arguments = args;
2388                      }
2389                      else if(propertyClass && propertyClass.type == structClass)
2390                      {
2391                         OldList * args = MkList();
2392                         char className[1024];
2393                         Declaration decl;
2394                         OldList * specs = MkList(), * decls = MkList();
2395                         Expression tempExp;
2396
2397                         // Make a declaration in the closest compound statement
2398                         // (Do not reuse (since using address for function calls)...)
2399
2400                         className[0] = 0;
2401                         FullClassNameCat(className, propertyClass.fullName, false); //true);
2402
2403                         //ListAdd(specs, MkSpecifierName(className));
2404                         ListAdd(specs, MkStructOrUnion(structSpecifier, MkIdentifier(className), null));
2405
2406                         sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2407
2408                         ListAdd(decls, MkInitDeclarator(
2409                            MkDeclaratorIdentifier(MkIdentifier(className)), null));
2410
2411                         decl = MkDeclaration(specs, decls);
2412                         if(curCompound)
2413                         {
2414                            if(!curCompound.compound.declarations)
2415                               curCompound.compound.declarations = MkList();
2416                            curCompound.compound.declarations->Insert(null, decl);
2417                         }
2418
2419                         tempExp = QMkExpId(className);
2420                         tempExp.expType = MkClassType(propertyClass.fullName);
2421
2422                         if(convertTo)
2423                         {
2424                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2425                            ListAdd(args, FixReference(ptr, true));
2426                         }
2427                         else
2428                         {
2429                            ListAdd(args, FixReference(ptr, true));
2430                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2431                         }
2432
2433                         if(exp.usage.usageDeepGet)
2434                         {
2435                            exp.type = callExp;
2436                            exp.call.exp = QMkExpId(nameToUse);
2437                            exp.call.arguments = args;
2438
2439                            FreeExpression(tempExp);
2440                         }
2441                         else
2442                         {
2443                            exp.type = bracketsExp;
2444                            exp.list = MkList();
2445                            ListAdd(exp.list, MkExpCall(QMkExpId(nameToUse),args));
2446                            if(exp.usage.usageMember)
2447                            {
2448                               ListAdd(exp.list, FixReference(tempExp, true));
2449                               exp.byReference = true;
2450                            }
2451                            else
2452                               ListAdd(exp.list, tempExp);
2453                         }
2454                      }
2455                      else
2456                      {
2457                         exp.type = callExp;
2458                         exp.call.exp = QMkExpId(nameToUse);
2459                         exp.call.arguments = MkList();
2460                         ListAdd(exp.call.arguments, FixReference(ptr, true));
2461                      }
2462                   }
2463                   else if(prop.conversion)
2464                   {
2465                      void * prev = exp.prev, * next = exp.next;
2466                      *exp = *exp.member.exp;
2467                      exp.prev = prev;
2468                      exp.next = next;
2469                   }
2470                }
2471             }
2472             else if(classProperty)
2473             {
2474                // Only process Gets here, Set is processed in opExp's '='
2475                if(exp.usage.usageGet)
2476                {
2477                   if(classProperty.Get)
2478                   {
2479                      Identifier id = exp.member.member;
2480                      Expression classExp = exp.member.exp;
2481
2482                      // Class Property
2483                      exp.type = callExp;
2484                      exp.call.exp = MkExpIdentifier(MkIdentifier("ecere::com::eClass_GetProperty"));
2485                      exp.call.arguments = MkList();
2486                      ListAdd(exp.call.arguments, classExp);
2487                      ListAdd(exp.call.arguments, MkExpString(QMkString(id.string)));
2488                      FreeIdentifier(id);
2489
2490                      ProcessExpression(exp);
2491                      return;
2492                   }
2493                }
2494             }
2495             else if(method)
2496             {
2497                // Get the function address if it's not called
2498                if((exp.usage.usageGet || exp.member.exp.expType.kind == subClassType) && !(exp.usage.usageCall))
2499                {
2500                   char name[1024];
2501
2502                   FreeIdentifier(exp.member.member);
2503
2504                   // Process this here since it won't be processed at the end...
2505                   exp.member.exp.usage.usageGet = true;
2506                   ProcessExpression(exp.member.exp);
2507                   // TEST: exp.tempCount = exp.member.exp.tempCount;
2508
2509                   if(method.type == virtualMethod)
2510                   {
2511                      strcpy(name, "__ecereVMethodID_");
2512                      FullClassNameCat(name, method._class.fullName, false);
2513                      strcat(name, "_");
2514                      strcat(name, method.name);
2515                      exp.type = indexExp;
2516                      if(memberClassSpecifier)
2517                      {
2518                         char className[1024];
2519                         // Need the class itself here...
2520                         strcpy(className, "__ecereClass_");
2521                         FullClassNameCat(className, _class.fullName, true);
2522                         MangleClassName(className);
2523
2524                         if(!_class.symbol)
2525                            _class.symbol = FindClass(_class.fullName);
2526                         DeclareClass(_class.symbol, className);
2527                         exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl"));
2528
2529                         // WHAT HAPPENS TO exp.member.exp ?
2530                      }
2531                      else
2532                      {
2533                         if(exp.thisPtr && _class.type != normalClass)
2534                         {
2535                            FreeExpression(exp.member.exp);
2536                            exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("_vTbl"));
2537                         }
2538                         else
2539                            exp.index.exp = MkExpPointer(exp.member.exp, MkIdentifier("_vTbl"));
2540                      }
2541                      exp.index.index = MkListOne(QMkExpId(name));
2542                      DeclareMethod(method, name);
2543                   }
2544                   else
2545                   {
2546                      FreeExpression(exp.member.exp);
2547                      exp.type = identifierExp;
2548                      strcpy(name, "__ecereMethod_");
2549                      FullClassNameCat(name, method._class.fullName, false);
2550                      strcat(name, "_");
2551                      strcat(name, method.name);
2552                      exp.identifier = MkIdentifier(name);
2553                      DeclareMethod(method, name);
2554                   }
2555                }
2556             }
2557             else if(member)
2558             {
2559                // Process this here since it won't be processed at the end...
2560                if(exp.usage.usageGet)
2561                {
2562                   exp.member.exp.usage.usageGet = true;   // Recently added this... is it ok?
2563                }
2564                ProcessExpression(exp.member.exp);
2565                // TEST: exp.tempCount = exp.member.exp.tempCount;
2566
2567                if(type.kind == classType)
2568                   DeclareStruct(type._class.registered.fullName, false);
2569
2570                // TESTING THIS NOHEAD STUFF...
2571                if(_class.type == noHeadClass)
2572                {
2573                   noHead = true;
2574                }
2575                else if(_class.type == structClass)
2576                {
2577                   changeToPtr = true;
2578                }
2579                else if(_class.type == bitClass)
2580                {
2581                   OldList * list = MkList();
2582                   char mask[32], shift[10];
2583                   OldList * specs = MkList();
2584                   BitMember bitMember = (BitMember) member;
2585                   Declarator decl = SpecDeclFromString(bitMember.dataTypeString, specs, null);
2586                   TypeName type = MkTypeName(specs, decl);
2587                   if(bitMember.mask > MAXDWORD)
2588                      sprintf(mask, FORMAT64HEXLL, bitMember.mask);
2589                   else
2590                      sprintf(mask, FORMAT64HEX, bitMember.mask);
2591                   sprintf(shift, "%d", bitMember.pos);
2592                   
2593                   FreeIdentifier(exp.member.member);
2594                  
2595                   // ((type) ((color & mask) >> bitPos))
2596                   ListAdd(list, MkExpCast(type, MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(MkListOne(
2597                      MkExpOp(exp.member.exp, '&', MkExpConstant(mask)))), RIGHT_OP, 
2598                         MkExpConstant(shift))))));
2599
2600                   exp.type = bracketsExp;
2601                   exp.list = list;
2602                }
2603                else if(_class.type == unitClass)
2604                {
2605                }
2606                else
2607                {
2608                   // If it's a this pointer, replace by precomputed shortcut
2609                   if(exp.member.exp.type == identifierExp && thisPtr && (!exp.member.exp.expType || !exp.member.exp.expType.typedByReference))
2610                   {
2611                      char pointerName[1024];
2612
2613                      strcpy(pointerName, "__ecerePointer_");
2614                      FullClassNameCat(pointerName, type._class.registered.fullName, false);
2615                      if(exp.member.exp.identifier)
2616                         FreeIdentifier(exp.member.exp.identifier);
2617                      exp.member.exp.identifier = MkIdentifier(pointerName);
2618                   }
2619                   // Otherwise, access the data the hard way
2620                   else
2621                   {
2622                      Expression bytePtr, e;
2623                      Expression classExp;
2624                      Expression checkedExp;
2625                      char structName[1024];
2626                      char className[1024];
2627                      strcpy(className, "__ecereClass_");
2628                      FullClassNameCat(className, member._class.fullName, true);
2629                      MangleClassName(className);
2630
2631                      // classExp = QMkExpId(className);
2632
2633                      if(!member._class.symbol)
2634                         member._class.symbol = FindClass(member._class.fullName);
2635
2636                      DeclareClass(member._class.symbol, className);
2637                      DeclareStruct(member._class.fullName, false);
2638
2639                      structName[0] = 0;
2640                      FullClassNameCat(structName, member._class.fullName, false);
2641
2642                      checkedExp = exp.member.exp;
2643                      while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list && checkedExp.list->count == 1) ||
2644                            checkedExp.type == castExp)
2645                      {
2646                         if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
2647                            checkedExp = checkedExp.list->last;
2648                         else if(checkedExp.type == castExp)
2649                            checkedExp = checkedExp.cast.exp;
2650                      }
2651
2652                      if(checkedExp.type != identifierExp &&
2653                         checkedExp.type != constantExp &&      // Added this here... Might mess up if we need address?
2654                         checkedExp.type != memberExp && checkedExp.type != pointerExp)
2655                      {
2656                         char ecereTemp[100];
2657                         Statement compound;
2658                         OldList * list = MkList();
2659                         Context context = PushContext();
2660                         if(exp.member.exp.tempCount > exp.tempCount)
2661                            exp.tempCount = exp.member.exp.tempCount;
2662
2663                         exp.tempCount++;
2664                         curExternal.function.tempCount = Max(curExternal.function.tempCount, exp.tempCount);
2665                         sprintf(ecereTemp, "__ecTemp%d", exp.tempCount);
2666                         curContext = context;
2667                         compound = MkCompoundStmt(
2668                            MkListOne(MkDeclaration(MkListOne(MkSpecifier(CHAR)), MkListOne(MkInitDeclarator(
2669                               MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier(ecereTemp))),
2670                                  MkInitializerAssignment(QBrackets(exp.member.exp)))))), null);
2671                         if(member._class.fixed)
2672                         {
2673                            if(member._class.templateClass ? member._class.templateClass.offset : member._class.offset)
2674                            {
2675                               char string[256];
2676                               sprintf(string, "%d", member._class.templateClass ? member._class.templateClass.offset : member._class.offset);
2677                               e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', MkExpConstant(string)));
2678                            }
2679                            else
2680                               e = QMkExpId(ecereTemp);
2681                         }
2682                         else
2683                         {
2684                            e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', 
2685                               MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
2686                         }
2687
2688                         compound.compound.context = context;
2689                         compound.compound.statements = MkListOne(MkExpressionStmt(MkListOne(
2690                            QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), 
2691                               MkDeclaratorPointer(MkPointer(null, null), null)), e)))));
2692
2693                         exp.member.exp =  MkExpExtensionCompound(compound);
2694
2695                         PopContext(context);
2696                         curContext = context.parent;
2697                      }
2698                      else
2699                      {
2700                         bytePtr = MkExpCast(QMkType("char", QMkPtrDecl(null)), /*CopyExpression(*/exp.member.exp/*)*/);
2701                         // DISABLED BECAUSE PREVENTS GETTING ADDRESS OF MEMBERS WITH ADDRESS 0
2702                         /*
2703                         e = QBrackets(QMkExpCond(exp.member.exp, 
2704                            QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(classExp, MkIdentifier("offset")))),
2705                            MkExpConstant("0")));
2706                         */
2707                         
2708                         // if(class.fixed)
2709                         if(member._class.fixed)
2710                         {
2711                            if(member._class.templateClass ? member._class.templateClass.offset : member._class.offset)
2712                            {
2713                               char string[256];
2714                               sprintf(string, "%d", member._class.templateClass ? member._class.templateClass.offset : member._class.offset);
2715                               e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string))));
2716                            }
2717                            else
2718                               e = bytePtr;
2719                         }
2720                         else
2721                            e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(QMkExpId(className), MkIdentifier("offset")))));
2722
2723                         // exp.member.exp = QBrackets(MkExpCast(QMkType(structName, QMkPtrDecl(null)), e));
2724                         exp.member.exp = QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), QMkPtrDecl(null)), e));
2725                      }
2726                   }
2727                   exp.type = pointerExp;
2728                }
2729             }
2730          }
2731
2732          // Take Out Any Class Specifier (Should have been used by now)
2733          FreeSpecifier(memberClassSpecifier);
2734
2735          // Just moved this at the end... How is it?
2736          if(exp.member.exp && (exp.type == memberExp || exp.type == pointerExp))
2737          {
2738             exp.member.exp.usage.usageGet = true;
2739             exp.member.exp.usage.usageMember = true;
2740             exp.member.exp.tempCount = exp.tempCount;
2741             ProcessExpression(exp.member.exp);
2742             exp.tempCount = exp.member.exp.tempCount;
2743             if((changeToPtr && exp.member.exp.byReference) || noHead)
2744                exp.type = pointerExp;
2745          }
2746          break;
2747       }
2748       case extensionCompoundExp:
2749       {
2750          Expression e = ((Statement)exp.compound.compound.statements->last).expressions->last;
2751          if(e)
2752             e.usage |= exp.usage & ExpUsage { usageGet = true, usageArg = true, usageMember = true };
2753
2754          ProcessStatement(exp.compound);
2755
2756          /*if(((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference)
2757             exp.byReference = ((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference;*/
2758          break;
2759       }
2760       case pointerExp:
2761       {
2762          exp.member.exp.usage.usageGet = true;
2763          ProcessExpression(exp.member.exp);
2764          break;
2765       }
2766       case typeSizeExp:
2767       {
2768          Specifier spec = exp.typeName.qualifiers ? exp.typeName.qualifiers->first : null;
2769          if(spec && spec.type == templateTypeSpecifier && !exp.typeName.declarator)
2770          {
2771             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, false);
2772             if(argExp)
2773             {
2774                Expression classExp;
2775                
2776                FreeTypeName(exp.typeName);
2777
2778                classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
2779
2780                exp.type = bracketsExp;
2781                exp.list = MkListOne(
2782                   MkExpCondition(MkExpBrackets(MkListOne(
2783                      MkExpOp(
2784                         MkExpOp(
2785                            MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, 
2786                               MkExpIdentifier(MkIdentifier("normalClass"))), 
2787                         OR_OP,
2788                         MkExpOp(
2789                            MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, 
2790                               MkExpIdentifier(MkIdentifier("noHeadClass"))
2791                             )))),
2792                      MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)))),
2793                      MkExpMember(classExp, MkIdentifier("typeSize")))
2794                   ); 
2795
2796                ProcessExpressionType(exp);
2797                ProcessExpression(exp);
2798             }
2799          }
2800          break;
2801       }
2802       case castExp:
2803       {
2804          if(exp.cast.exp)
2805          {
2806             exp.cast.exp.usage |= exp.usage & ExpUsage { usageGet = true, usageMember = true };
2807             ProcessExpression(exp.cast.exp);
2808             // TESTING THIS
2809             if(exp.cast.exp.byReference)
2810                exp.byReference = exp.cast.exp.byReference;
2811             if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass &&
2812                exp.cast.exp.expType && (exp.cast.exp.expType.kind == pointerType || exp.cast.exp.expType.kind == arrayType || (
2813                   exp.cast.exp.expType.kind == classType && exp.cast.exp.expType._class && exp.cast.exp.expType._class.registered && 
2814                      !strcmp(exp.cast.exp.expType._class.registered.dataTypeString, "char *")) ) )
2815                exp.byReference = true;
2816          }
2817          // Moved this to 1.5...
2818          //exp.expType = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
2819          break;
2820       }
2821       case conditionExp:
2822       {
2823          Expression e;
2824          if(exp.usage.usageGet)
2825             exp.cond.cond.usage.usageGet = true;
2826          ProcessExpression(exp.cond.cond);
2827          for(e = exp.cond.exp->first; e; e = e.next)
2828          {
2829             if(!e.next && exp.usage.usageGet) e.usage.usageGet = true;
2830             ProcessExpression(e);
2831          }
2832          if(exp.usage.usageGet)
2833             exp.cond.elseExp.usage.usageGet = true;
2834          ProcessExpression(exp.cond.elseExp);
2835          break;
2836       }
2837       case classExp:
2838       {
2839          // Need the class itself here...
2840          if(exp._classExp.specifiers && exp._classExp.specifiers->first && ((Specifier)exp._classExp.specifiers->first).type == templateTypeSpecifier)
2841          {
2842             Specifier spec = exp._classExp.specifiers->first;
2843             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, true);
2844             if(argExp)
2845             {
2846                FreeList(exp._classExp.specifiers, FreeSpecifier);
2847                if(exp._classExp.decl)
2848                   FreeDeclarator(exp._classExp.decl);
2849
2850                exp.type = memberExp; //pointerExp;
2851                exp.member.exp = argExp;
2852                exp.member.member = MkIdentifier("dataTypeClass");
2853
2854                ProcessExpressionType(argExp);
2855                ProcessExpression(exp);
2856             }
2857          }
2858          else
2859          {
2860             char className[1024];
2861             char * string = StringFromSpecDecl(exp._classExp.specifiers, exp._classExp.decl);
2862             Symbol classSym = FindClass(string);
2863             
2864             strcpy(className, "__ecereClass_");
2865             FullClassNameCat(className, string, true);      // TODO: Verify this
2866             MangleClassName(className);
2867             DeclareClass(classSym, className);
2868             delete string;
2869
2870             FreeList(exp._classExp.specifiers, FreeSpecifier);
2871             if(exp._classExp.decl)
2872                FreeDeclarator(exp._classExp.decl);
2873
2874             exp.type = identifierExp;
2875             exp.identifier = MkIdentifier(className);
2876          }
2877          break;
2878       }
2879       case vaArgExp:
2880       {
2881          ProcessExpression(exp.vaArg.exp);
2882          break;
2883       }
2884       case extensionInitializerExp:
2885       {
2886          ProcessInitializer(exp.initializer.initializer);
2887          break;
2888       }
2889    }
2890    FixRefExp(exp);
2891    yylloc = oldyylloc;
2892 }
2893
2894 static void ProcessInitializer(Initializer init)
2895 {
2896    switch(init.type)
2897    {
2898       case expInitializer:
2899          init.exp.usage.usageGet = true;
2900          ProcessExpression(init.exp);
2901          if(init.exp.destType && init.exp.destType.kind == classType && init.exp.destType._class &&
2902             init.exp.destType._class.registered && init.exp.destType._class.registered.type == noHeadClass)
2903          {
2904             FixReference(init.exp, true);
2905          }
2906          else if(init.exp.destType && init.exp.destType.kind == classType)
2907             FixReference(init.exp, false);
2908          break;
2909       case listInitializer:
2910       {
2911          Initializer i;
2912          for(i = init.list->first; i; i = i.next)
2913             ProcessInitializer(i);
2914          break;
2915       }
2916    }
2917 }
2918
2919 static void ProcessDeclaration(Declaration decl)
2920 {
2921    switch(decl.type)
2922    {
2923       case initDeclaration:
2924       {
2925          if(decl.declarators)
2926          {
2927             InitDeclarator d;
2928          
2929             for(d = decl.declarators->first; d; d = d.next)
2930             {
2931                if(d.initializer)
2932                   ProcessInitializer(d.initializer);
2933             }
2934          }
2935          break;
2936       }
2937    }
2938 }
2939
2940 static void ProcessStatement(Statement stmt)
2941 {
2942    switch(stmt.type)
2943    {
2944       case labeledStmt:
2945          ProcessStatement(stmt.labeled.stmt);
2946          break;
2947       case caseStmt:
2948          if(stmt.caseStmt.exp)
2949          {
2950             stmt.caseStmt.exp.usage.usageGet = true;
2951
2952             // This expression should be constant...
2953             ProcessExpression(stmt.caseStmt.exp);
2954          }
2955          if(stmt.caseStmt.stmt)
2956             ProcessStatement(stmt.caseStmt.stmt);
2957          break;
2958       case compoundStmt:
2959       {
2960          if(stmt.compound.context)
2961          {
2962             Declaration decl;
2963             Statement s;
2964             Statement prevCompound = curCompound;
2965             Context prevContext = curContext;
2966
2967             if(!stmt.compound.isSwitch)
2968             {
2969                curCompound = stmt;
2970                curContext = stmt.compound.context;
2971             }
2972
2973             if(stmt.compound.declarations)
2974             {
2975                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
2976                   ProcessDeclaration(decl);
2977             }
2978             if(stmt.compound.statements)
2979             {
2980                for(s = stmt.compound.statements->first; s; s = s.next)
2981                   ProcessStatement(s);
2982             }
2983             curContext = prevContext;
2984             curCompound = prevCompound;
2985          }
2986          break;
2987       }
2988       case expressionStmt:
2989       {
2990          Expression exp;
2991          if(stmt.expressions)
2992          {
2993             for(exp = stmt.expressions->first; exp; exp = exp.next)
2994             {
2995                ProcessExpression(exp);
2996             }
2997          }
2998          break;
2999       }
3000       case ifStmt:
3001       {
3002          if(stmt.ifStmt.exp)
3003          {
3004             Expression exp;
3005
3006             ((Expression)stmt.ifStmt.exp->last).usage.usageGet = true;
3007             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
3008             {
3009                ProcessExpression(exp);
3010             }
3011          }
3012          if(stmt.ifStmt.stmt)
3013             ProcessStatement(stmt.ifStmt.stmt);
3014          if(stmt.ifStmt.elseStmt)
3015             ProcessStatement(stmt.ifStmt.elseStmt);
3016          break;
3017       }
3018       case switchStmt:
3019       {
3020          Expression exp;
3021          ((Expression)stmt.switchStmt.exp->last).usage.usageGet = true;
3022          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
3023          {
3024             ProcessExpression(exp);
3025          }
3026          ProcessStatement(stmt.switchStmt.stmt);
3027          break;
3028       }
3029       case whileStmt:
3030       {
3031          Expression exp;
3032          ((Expression)stmt.whileStmt.exp->last).usage.usageGet = true;
3033          for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
3034          {
3035             ProcessExpression(exp);
3036          }
3037          ProcessStatement(stmt.whileStmt.stmt);
3038          break;
3039       }
3040       case doWhileStmt:
3041       {
3042          Expression exp;
3043          if(stmt.doWhile.exp && stmt.doWhile.exp->last)
3044          {
3045             ((Expression)stmt.doWhile.exp->last).usage.usageGet = true;
3046             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
3047             {
3048                ProcessExpression(exp);
3049             }
3050          }
3051          if(stmt.doWhile.stmt)
3052             ProcessStatement(stmt.doWhile.stmt);
3053          break;
3054       }
3055       case forStmt:
3056       {
3057          Expression exp;
3058          if(stmt.forStmt.init)
3059             ProcessStatement(stmt.forStmt.init);
3060
3061          if(stmt.forStmt.check)
3062          {
3063             if(stmt.forStmt.check.expressions)
3064             {
3065                ((Expression)stmt.forStmt.check.expressions->last).usage.usageGet = true;
3066             }
3067             ProcessStatement(stmt.forStmt.check);
3068          }
3069          if(stmt.forStmt.increment)
3070          {        
3071             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
3072             {
3073                ProcessExpression(exp);
3074             }
3075          }
3076          if(stmt.forStmt.stmt)
3077             ProcessStatement(stmt.forStmt.stmt);
3078          break;
3079       }
3080       case gotoStmt:
3081          break;
3082       case continueStmt:
3083          break;
3084       case breakStmt:
3085          break;
3086       case returnStmt:
3087       {
3088          Expression exp;
3089          if(stmt.expressions)
3090          {
3091             ((Expression)stmt.expressions->last).usage.usageGet = true;
3092             for(exp = stmt.expressions->first; exp; exp = exp.next)
3093             {
3094                ProcessExpression(exp);
3095                // TOCHECK: This was added 2013/02/09 as part of 64 bit port for structs in class properties to automatically be returned by reference
3096                if(!exp.next && exp.destType && exp.destType.byReference)
3097                   FixReference(exp, true);
3098             }
3099          }
3100          break;
3101       }
3102       case badDeclarationStmt:
3103       {
3104          ProcessDeclaration(stmt.decl);
3105          break;
3106       }
3107       case asmStmt:
3108       {
3109          AsmField field;
3110          if(stmt.asmStmt.inputFields)
3111          {
3112             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
3113                if(field.expression)
3114                   ProcessExpression(field.expression);
3115          }
3116          if(stmt.asmStmt.outputFields)
3117          {
3118             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
3119                if(field.expression)
3120                   ProcessExpression(field.expression);
3121          }
3122          if(stmt.asmStmt.clobberedFields)
3123          {
3124             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
3125                if(field.expression)
3126                   ProcessExpression(field.expression);
3127          }
3128          break;
3129       }
3130    }
3131 }
3132
3133 static void ProcessFunction(FunctionDefinition function)
3134 {
3135    if(function.body)
3136       ProcessStatement(function.body);
3137 }
3138
3139 static void ProcessMemberInitData(MemberInit member)
3140 {
3141    if(member.initializer)
3142       ProcessInitializer(member.initializer);
3143 }
3144
3145 static void ProcessInstantiation(Instantiation inst)
3146 {
3147    if(inst.members)
3148    {
3149       MembersInit members;
3150       for(members = inst.members->first; members; members = members.next)
3151       {
3152          if(members.type == dataMembersInit)
3153          {
3154             if(members.dataMembers)
3155             {
3156                MemberInit member;
3157                for(member = members.dataMembers->first; member; member = member.next)
3158                   ProcessMemberInitData(member);
3159             }
3160          }
3161          else if(members.type == methodMembersInit)
3162          {
3163             ProcessFunction((FunctionDefinition)members.function);
3164          }
3165       }
3166    }
3167 }
3168
3169 /////////// MEMBER ACCESS PASS /////////////////////////////////////////////
3170 public void ProcessMemberAccess()
3171 {
3172    External external;
3173    for(external = ast->first; external; external = external.next)
3174    {
3175       curExternal = external;
3176       // There shouldn't be any class member access here anyways...
3177       if(external.type == declarationExternal)
3178       {
3179          if(external.declaration)
3180             ProcessDeclaration(external.declaration);
3181       }
3182    }
3183    
3184    for(external = ast->first; external; external = external.next)
3185    {
3186       curExternal = external;
3187       if(external.type == functionExternal)
3188       {
3189          ProcessFunction(external.function);
3190       }
3191       else if(external.type == declarationExternal)
3192       {
3193          //currentClass = external.function._class;
3194          if(external.declaration)
3195             ProcessDeclaration(external.declaration);
3196       }
3197       else if(external.type == classExternal)
3198       {
3199          ClassDefinition _class = external._class;
3200          //currentClass = external.symbol.registered;
3201          if(_class.definitions)
3202          {
3203             ClassDef def;
3204             Class regClass = _class.symbol.registered;
3205
3206             // Process all functions
3207             for(def = _class.definitions->first; def; def = def.next)
3208             {
3209                if(def.type == functionClassDef)
3210                {
3211                   curExternal = def.function.declarator.symbol.pointerExternal;
3212                   ProcessFunction((FunctionDefinition)def.function);
3213                }
3214                else if(def.type == declarationClassDef && def.decl.type == instDeclaration)
3215                {
3216                   ProcessInstantiation(def.decl.inst);
3217                }
3218                else if(def.type == defaultPropertiesClassDef && def.defProperties)
3219                {
3220                   MemberInit defProperty;
3221
3222                   // Add this to the context
3223                   Symbol thisSymbol
3224                   {
3225                      string = CopyString("this");
3226                      type = MkClassType(regClass.fullName);
3227                   };
3228                   globalContext.symbols.Add((BTNode)thisSymbol);
3229                   
3230                   for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
3231                   {
3232                      //thisClass = regClass;
3233                      ProcessMemberInitData(defProperty); //, regClass, &id);
3234                      //thisClass = null;
3235                   }
3236
3237                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3238                   globalContext.symbols.Remove((BTNode)thisSymbol);
3239                   FreeSymbol(thisSymbol);
3240                }
3241                else if(def.type == propertyClassDef && def.propertyDef)
3242                {
3243                   PropertyDef prop = def.propertyDef;
3244
3245                   // Add this to the context
3246                   Symbol thisSymbol
3247                   {
3248                      string = CopyString("this");
3249                      type = MkClassType(regClass.fullName);
3250                   };
3251                   globalContext.symbols.Add((BTNode)thisSymbol);
3252                   
3253                   //thisClass = regClass;
3254                   if(prop.setStmt)
3255                   {
3256                      curExternal = prop.symbol.externalSet;
3257                      ProcessStatement(prop.setStmt);
3258                   }
3259                   if(prop.getStmt)
3260                   {
3261                      curExternal = prop.symbol.externalGet;
3262                      ProcessStatement(prop.getStmt);
3263                   }
3264                   if(prop.issetStmt)
3265                   {
3266                      curExternal = prop.symbol.externalIsSet;
3267                      ProcessStatement(prop.issetStmt);
3268                   }
3269
3270                   //thisClass = null;
3271
3272                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3273                   globalContext.symbols.Remove((BTNode)thisSymbol);
3274                   FreeSymbol(thisSymbol);
3275                }
3276                else if(def.type == classPropertyClassDef && def.propertyDef)
3277                {
3278                   PropertyDef prop = def.propertyDef;
3279
3280                   //thisClass = regClass;
3281                   if(prop.setStmt)
3282                   {
3283                      curExternal = prop.symbol.externalSet;
3284                      ProcessStatement(prop.setStmt);
3285                   }
3286                   if(prop.getStmt)
3287                   {
3288                      curExternal = prop.symbol.externalGet;
3289                      ProcessStatement(prop.getStmt);
3290                   }
3291                   //thisClass = null;
3292                }
3293                else if(def.type == propertyWatchClassDef && def.propertyWatch)
3294                {
3295                   PropertyWatch propertyWatch = def.propertyWatch;
3296         
3297                   // Add this to the context
3298                   Symbol thisSymbol
3299                   {
3300                      string = CopyString("this");
3301                      type = MkClassType(regClass.fullName);
3302                   };
3303                   globalContext.symbols.Add((BTNode)thisSymbol);
3304                   
3305                   //thisClass = regClass;
3306                   if(propertyWatch.compound)
3307                   {
3308                      Symbol thisSymbol
3309                      {
3310                         string = CopyString("this");
3311                         type = MkClassType(regClass.fullName);
3312                      };
3313                      propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
3314                      curExternal = null;
3315                      ProcessStatement(propertyWatch.compound);
3316                   }
3317                   // thisClass = null;
3318
3319                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3320                   globalContext.symbols.Remove((BTNode)thisSymbol);
3321                   FreeSymbol(thisSymbol);
3322                }
3323             }
3324          }
3325       }
3326    }
3327 }