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