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