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