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