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