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          Expression expCallExp = exp.call.exp;
1647          OldList * arguments = exp.call.arguments;
1648          bool handleNullVMethod = false;
1649          TypeName typeName = null;
1650
1651          if(arguments)
1652          {
1653             for(e = arguments->first; e; e = e.next)
1654             {
1655                e.usage.usageGet = true;
1656                e.usage.usageArg = true;
1657                e.tempCount = Max(e.tempCount, exp.tempCount);
1658                ProcessExpression(e);
1659                exp.tempCount = Max(exp.tempCount, e.tempCount);
1660             }
1661          }
1662          expCallExp.usage.usageGet = true;
1663          expCallExp.usage.usageCall = true;
1664          expCallExp.tempCount = exp.tempCount;
1665
1666          ProcessExpression(expCallExp);
1667
1668          if(expCallExp.expType && expCallExp.expType.kind == methodType)
1669          {
1670             bool nullMemberExp = false;
1671             Expression memberExp = (expCallExp.type == ExpressionType::memberExp) ? expCallExp : null;
1672
1673             Class _class = expCallExp.expType.methodClass;     // For Virtual Method
1674             Class argClass = expCallExp.expType.methodClass;  // Class actually passed
1675             Method method = expCallExp.expType.method;
1676             if(method.type == virtualMethod)
1677             {
1678                char name[1024];
1679                Declarator decl;
1680                Context back;
1681                OldList * specs = MkList();
1682                strcpy(name, "__ecereVMethodID_");
1683                FullClassNameCat(name, method._class.fullName, false);
1684                strcat(name, "_");
1685                strcat(name, method.name);
1686
1687                DeclareMethod(curExternal, method, name);
1688
1689                back = curContext;
1690                // THIS SpecDeclFromString HERE SHOULD WORK WITH THE METHOD TEMPLATE PARAMETERS...
1691                curContext = (method._class.symbol) ? ((Symbol)method._class.symbol).ctx : globalContext;
1692                // Cast function to its type
1693                {
1694                   Context context = SetupTemplatesContext(method._class);
1695
1696                   decl = SpecDeclFromString(method.dataTypeString, specs, MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), null)));
1697
1698                   FinishTemplatesContext(context);
1699                }
1700                curContext = back;
1701                if(method.dataType && !method.dataType.staticMethod)
1702                {
1703                   Declarator funcDecl = GetFuncDecl(decl);
1704
1705                   if(!funcDecl.function.parameters)
1706                      funcDecl.function.parameters = MkList();
1707                   {
1708                      TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
1709                      Specifier firstSpec = firstParam ? firstParam.qualifiers->first : null;
1710
1711                      if(firstParam && firstSpec && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
1712                      {
1713                         funcDecl.function.parameters->Remove(funcDecl.function.parameters->first);
1714                         FreeTypeName(firstParam);
1715                      }
1716                   }
1717
1718                   if(method.dataType.thisClass && !strcmp(method.dataType.thisClass.string, "class"))
1719                   {
1720                      TypeName param;
1721                      typedObject = true;
1722
1723                      param = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null));
1724                      param.qualifiers->Insert(null, MkSpecifier(CONST));
1725                      funcDecl.function.parameters->Insert(null, param);
1726                      // Testing this for any_object::
1727                      if(!method.dataType.extraParam)
1728                      {
1729                         funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null)), MkDeclaratorPointer(MkPointer(null,null), null)));
1730                         DeclareStruct(curExternal, "ecere::com::Class", false, true);
1731                      }
1732                   }
1733                   else
1734                   {
1735                      funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(
1736                         /*MkClassName*/MkSpecifierName(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)), null));
1737                   }
1738                }
1739
1740                typeName = MkTypeName(specs, decl);
1741
1742                if(memberExp && memberExp.member.exp.expType)
1743                {
1744                   Type type = memberExp.member.exp.expType;
1745
1746                   if(type.kind == classType && type._class && type._class.registered)
1747                   {
1748                      Class regClass = type._class.registered;
1749                      ClassType classType = regClass.type;
1750                      if(classType != normalClass || !strcmp(regClass.dataTypeString, "char *") || (method.dataType.byReference))// TESTING THIS OUT: && !memberExp.member.exp.expType.classObjectType)
1751                         argClass = regClass;
1752                   }
1753                   else if(type.kind == subClassType)
1754                   {
1755                      argClass = FindClass("ecere::com::Class").registered;
1756                   }
1757                   else if((type.kind == arrayType || type.kind == pointerType) && type.type && type.type.kind == charType)
1758                   {
1759                      argClass = FindClass("char *").registered;
1760                   }
1761                   else if(type.kind == pointerType)
1762                   {
1763                      argClass = eSystem_FindClass(privateModule, "uintptr");
1764                      FreeType(memberExp.member.exp.expType);
1765                      memberExp.member.exp.expType = ProcessTypeString("uintptr", false);
1766                      memberExp.member.exp.byReference = true;
1767                   }
1768                   else
1769                   {
1770                      char string[1024] = "";
1771                      Symbol classSym;
1772                      PrintTypeNoConst(type, string, false, true);
1773                      classSym = FindClass(string);
1774                      if(classSym) argClass = classSym.registered;
1775                   }
1776
1777                   /*
1778                   if(!_class && argClass && strcmp(argClass.fullName, "class"))
1779                      _class = argClass;
1780                   */
1781                }
1782
1783                {
1784                   Type type = memberExp ? memberExp.member.exp.expType : null;
1785                   Class regClass = (type && type.kind == classType && type._class) ? type._class.registered : null;
1786                   char className[1024];
1787
1788                   // Added !exp.call.exp.expType.methodClass
1789                   if(!expCallExp.expType.methodClass && !_class && type && type.classObjectType)
1790                      strcpy(className, "class");
1791                   else
1792                   {
1793                      Class cl = _class;
1794                      // TESTING: Moved this here...
1795                      if(!cl && argClass && strcmp(argClass.fullName, "class"))
1796                         cl = argClass;
1797                      if(!cl)
1798                         cl = regClass;
1799                      if(!cl)
1800                         // TODO: Unhandled case here, what should happen?
1801                         cl = class(int);
1802
1803                      // To avoid declaring classes templatized after this class template (e.g. public struct Iterator<class T, class IT = int> { Container<T, IT> container; } )
1804                      if(cl.templateClass && !_class && expCallExp.expType._class && !expCallExp.expType.methodClass &&
1805                         (type.kind == subClassType || (regClass && regClass.type == normalClass && strcmp(regClass.dataTypeString, "char *"))))
1806                         cl = cl.templateClass;
1807
1808                      // Need the class itself here...
1809                      strcpy(className, "__ecereClass_");
1810                      FullClassNameCat(className, cl.fullName, true);
1811
1812                      if(!cl.symbol)
1813                         cl.symbol = FindClass(cl.fullName);
1814
1815                      DeclareClass(curExternal, cl.symbol, className);
1816                   }
1817
1818                   if(type && type.kind == subClassType && !_class && !expCallExp.expType.methodClass && memberExp)
1819                   {
1820                      expCallExp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1821                         MkExpIndex(MkExpPointer(CopyExpression(memberExp.member.exp), MkIdentifier("_vTbl")),
1822                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1823
1824                      handleNullVMethod = true;
1825                   }
1826                   else if(_class || expCallExp.expType.methodClass || !memberExp ||
1827                          !regClass || regClass.type != normalClass || !strcmp(regClass.dataTypeString, "char *"))
1828                   {
1829                      if(!memberExp)
1830                         FreeExpression(expCallExp);
1831                      expCallExp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1832                         MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl")),
1833                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1834
1835                      handleNullVMethod = true;
1836                   }
1837                   else
1838                   {
1839                      // TOCHECK: Added this if statement here for File::OnSerialize to be calling the instance's own Seek function,
1840                      // as opposed to the File class vTbl one
1841
1842                      // ({ Instance __internal_ClassInst = e; __internal_ClassInst ? __internal_ClassInst._vTbl : __ecereClass_...; })
1843                      Expression vTblExp;
1844                      Context context = PushContext();
1845                      OldList * specs;
1846                      OldList * declList = MkListOne(MkDeclaration(
1847                               (specs = MkListOne(MkSpecifierName("Instance"))),
1848                               MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_ClassInst")),
1849                                  MkInitializerAssignment(CopyExpression(memberExp.member.exp))))));
1850                      OldList * stmtList = MkListOne(MkExpressionStmt(MkListOne(MkExpCondition(
1851                               MkExpIdentifier(MkIdentifier("__internal_ClassInst")),
1852                               MkListOne(MkExpPointer(MkExpIdentifier(MkIdentifier("__internal_ClassInst")), MkIdentifier("_vTbl"))),
1853                               MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl"))))));
1854
1855                      vTblExp = MkExpExtensionCompound(MkCompoundStmt(declList, stmtList));
1856
1857                      if(type.specConst)
1858                         specs->Insert(null, MkSpecifier(CONST));
1859
1860                      vTblExp.loc = exp.loc;
1861                      vTblExp.compound.compound.context = context;
1862                      PopContext(context);
1863
1864                      expCallExp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1865                         MkExpIndex(vTblExp, MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1866
1867                      handleNullVMethod = true;
1868                   }
1869                }
1870             }
1871             else
1872             {
1873                char name[1024];
1874                strcpy(name, "__ecereMethod_");
1875                FullClassNameCat(name, method._class.fullName, false);
1876                strcat(name, "_");
1877                strcat(name, method.name);
1878
1879                if(!memberExp)
1880                   FreeExpression(expCallExp);
1881                expCallExp = MkExpIdentifier(MkIdentifier(name));
1882                DeclareMethod(curExternal, method, name);
1883                if(memberExp && memberExp.expType && method.dataType)
1884                {
1885                   expCallExp.expType = method.dataType;
1886                   method.dataType.refCount++;
1887                }
1888             }
1889             if(memberExp && (!memberExp.member.exp || !memberExp.member.exp.expType || memberExp.member.exp.expType.kind != subClassType))
1890             {
1891                if(method.dataType && !method.dataType.staticMethod && !method.dataType.extraParam)
1892                {
1893                   if(!arguments)
1894                      arguments = MkList();
1895
1896                   // Testing this (COMMENTED OUT TESTING, CALLING METHODS ON ENUM/UNIT ADDED & IN FRONT OF VARIABLES
1897                   /*
1898                   if(memberExp.member.exp.expType.kind != classType ||
1899                      memberExp.member.exp.expType._class.registered.type == enumClass ||
1900                      memberExp.member.exp.expType._class.registered.type == unitClass)
1901                   {
1902                      char typeString[1024] = "";
1903                      if(memberExp.member.exp.expType.kind != classType)
1904                         PrintType(memberExp.member.exp.expType, typeString, false, true);
1905                      else
1906                         strcpy(typeString, memberExp.member.exp.expType._class.registered.dataTypeString);
1907
1908                      // THIS WAS NASTY:
1909                      // memberExp.member.exp.expType.kind = classType;
1910                      // memberExp.member.exp.expType._class = FindClass(typeString);
1911
1912                      FreeType(memberExp.member.exp.expType);
1913                      memberExp.member.exp.expType = Type
1914                      {
1915                         kind = classType;
1916                         _class = FindClass(typeString);
1917                         refCount = 1;
1918                      };
1919
1920                      // Default to an int instead
1921                      if(!memberExp.member.exp.expType._class)
1922                      {
1923                         // TODO: Shouldn't get here...
1924                         memberExp.member.exp.expType.kind = TypeInt;
1925                      }
1926                   }
1927                   */
1928
1929                   if(typedObject && memberExp.member.exp && memberExp.member.exp.expType)
1930                   {
1931                      bool changeReference = false;
1932                      bool stillAddReferenceOp = false;
1933                      Expression memberExpMemberExp = CopyExpression(memberExp.member.exp);
1934                      Type expType = memberExp.member.exp.expType;
1935                      Class c = expType.kind == classType && expType._class ? expType._class.registered : null;
1936
1937                      // Patched so that class isn't considered SYSTEM...
1938                      if(argClass && (argClass.type == enumClass || argClass.type == unitClass || argClass.type == bitClass || argClass.type == systemClass) && strcmp(argClass.fullName, "class") &&
1939                         strcmp(argClass.fullName, "uintptr") && strcmp(argClass.fullName, "intptr"))
1940                         changeReference = true;
1941                      if(!expType.classObjectType && ( ( (expType.kind != pointerType && (!c || c.type == structClass) ) ) || method.dataType.byReference) ) // ADDED THIS FOR OnGetDataFromString
1942                      {
1943                         if(c && (c.type == normalClass || c.type == noHeadClass))
1944                            stillAddReferenceOp = true;
1945                         changeReference = true;
1946                      }
1947                      if(typedObject && expType.classObjectType && expType.byReference != method.dataType.byReference)
1948                         changeReference = true;
1949                      if(changeReference)
1950                      {
1951                         if(memberExp.member.exp.type == bracketsExp && memberExp.member.exp.list && memberExp.member.exp.list->count == 1 &&
1952                            ((Expression)memberExp.member.exp.list->first).type == opExp && ((Expression)memberExp.member.exp.list->first).op.op == '*' && !((Expression)memberExp.member.exp.list->first).op.exp1)
1953                         {
1954                            arguments->Insert(null, ((Expression)memberExp.member.exp.list->first).op.exp2);
1955                            ((Expression)memberExp.member.exp.list->first).op.exp2 = null;
1956                         }
1957                         else if(memberExp.member.exp.type == opExp && memberExp.member.exp.op.op == '*' && !memberExp.member.exp.op.exp1)
1958                         {
1959                            arguments->Insert(null, memberExp.member.exp.op.exp2);
1960                            memberExp.member.exp.op.exp2 = null;
1961                         }
1962                         else if(!memberExp.member.exp.byReference || stillAddReferenceOp)
1963                         {
1964                            // TESTING THIS... REUSE THIS CODE?
1965                            Expression checkedExp = memberExp.member.exp;
1966                            Expression parentExp = null;
1967                            Expression newExp;
1968                            bool disconnected = false;
1969                            while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list) || checkedExp.type == castExp)
1970                            {
1971                               parentExp = checkedExp;
1972
1973                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
1974                               {
1975                                  checkedExp = checkedExp.list->last;
1976                                  // Dissociate from memberExp which will get freed
1977                                  if(checkedExp && !disconnected)
1978                                  {
1979                                     parentExp.list->Remove(checkedExp);
1980                                     disconnected = true;
1981                                  }
1982                               }
1983                               else if(checkedExp.type == castExp)
1984                               {
1985                                  checkedExp = checkedExp.cast.exp;
1986                                  // Dissociate from memberExp which will get freed
1987                                  if(checkedExp && !disconnected)
1988                                  {
1989                                     checkedExp.cast.exp = null;
1990                                     disconnected = true;
1991                                  }
1992                               }
1993                            }
1994                            if(!parentExp)
1995                               nullMemberExp = true;
1996
1997                            if(typedObject && !expType.classObjectType && !stillAddReferenceOp)
1998                               newExp = checkedExp;
1999                            else
2000                            {
2001                               newExp = MkExpOp(null, '&', checkedExp);
2002                               newExp.byReference = true;
2003                            }
2004                            if(parentExp && (parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp))
2005                            {
2006                               parentExp.list->Remove(checkedExp);
2007                               parentExp.list->Add(newExp);
2008                            }
2009                            else if(parentExp && parentExp.type == castExp)
2010                            {
2011                               parentExp.cast.exp = newExp;
2012                               // Add a dereference level here
2013                               if(newExp.expType && newExp.expType.classObjectType)
2014                                  parentExp.cast.typeName.declarator = MkDeclaratorPointer(MkPointer(null, null), parentExp.cast.typeName.declarator);
2015                            }
2016                            if(typedObject && !expType.classObjectType)
2017                            {
2018                               Type destType { refCount = 1, kind = classType, classObjectType = ClassObjectType::anyObject };
2019                               FreeType((parentExp ? parentExp : newExp).expType);
2020                               FreeType((parentExp ? parentExp : newExp).destType);
2021                               (parentExp ? parentExp : newExp).expType = checkedExp.expType;
2022                               (parentExp ? parentExp : newExp).destType = destType;
2023                               if(checkedExp.expType) checkedExp.expType.refCount++;
2024                            }
2025                            arguments->Insert(null, parentExp ? parentExp : newExp);
2026                         }
2027                         else
2028                         {
2029                            arguments->Insert(null, memberExp.member.exp);
2030                            nullMemberExp = true;
2031                         }
2032                      }
2033                      else
2034                      {
2035                         arguments->Insert(null, memberExp.member.exp);
2036                         nullMemberExp = true;
2037                      }
2038
2039                      {
2040                         char className[1024];
2041                         Type type = memberExp.member.exp ? memberExp.member.exp.expType : null;
2042                         Class regClass = (type && type.kind == classType && type._class) ? type._class.registered : null;
2043                         Class cl = argClass ? argClass : regClass;
2044                         className[0] = 0;
2045
2046                         if(memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.classObjectType == ClassObjectType::typedObject)
2047                            strcpy(className, "class");
2048                         else if(cl)
2049                         {
2050                            // Need the class itself here...
2051                            strcpy(className, "__ecereClass_");
2052                            FullClassNameCat(className, cl.fullName, true);
2053
2054                            if(!cl.symbol)
2055                               cl.symbol = FindClass(cl.fullName);
2056                            DeclareClass(curExternal, cl.symbol, className);
2057                         }
2058
2059                         if(className[0])
2060                         {
2061                            if(memberExp && cl && cl.type == normalClass && (!type || type.byReference == false) && strcmp(cl.dataTypeString, "char *"))
2062                            {
2063                               // ({ Instance __internal_ClassInst = e; __internal_ClassInst ? __internal_ClassInst._class : __ecereClass_...; })
2064                               Expression c;
2065                               Context context = PushContext();
2066                               OldList * specs;
2067
2068                               c = MkExpExtensionCompound(MkCompoundStmt(
2069                                     MkListOne(MkDeclaration(
2070                                        (specs = MkListOne(MkSpecifierName("Instance"))),
2071                                        MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_ClassInst")),
2072                                           MkInitializerAssignment(memberExpMemberExp))))),
2073                                     MkListOne(MkExpressionStmt(MkListOne(MkExpCondition(
2074                                        MkExpIdentifier(MkIdentifier("__internal_ClassInst")),
2075                                        MkListOne(MkExpPointer(MkExpIdentifier(MkIdentifier("__internal_ClassInst")), MkIdentifier("_class"))),
2076                                        MkExpIdentifier(MkIdentifier(className))))))));
2077                               c.compound.compound.context = context;
2078                               PopContext(context);
2079
2080                               if(type.specConst)
2081                                  specs->Insert(null, MkSpecifier(CONST));
2082
2083                               arguments->Insert(null, c);
2084
2085                               memberExpMemberExp = null; // We used this
2086                            }
2087                            else
2088                               arguments->Insert(null, MkExpIdentifier(MkIdentifier(className)));
2089                         }
2090                      }
2091
2092                      if(memberExpMemberExp)
2093                         FreeExpression(memberExpMemberExp);
2094                   }
2095                   else
2096                   {
2097                      arguments->Insert(null, memberExp.member.exp);
2098                      nullMemberExp = true;
2099                   }
2100                }
2101             }
2102             /*else if(method->dataType)
2103             {
2104             }*/
2105             if(memberExp)
2106             {
2107                if(nullMemberExp)
2108                   memberExp.member.exp = null;
2109                FreeExpression(memberExp);
2110             }
2111          }
2112
2113          if(arguments)
2114          {
2115             for(e = arguments->first; e; e = e.next)
2116             {
2117                Type destType = (e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : e.destType;
2118                //if(e.destType && e.destType.kind == classType && e.destType._class && !strcmp(e.destType._class.string, "class"))
2119                //if(e.destType && (e.destType.classObjectType == ClassObjectType::typedObject || e.destType.classObjectType == anyObject))
2120                if(destType && (destType.classObjectType == ClassObjectType::typedObject || destType.classObjectType == anyObject))
2121                {
2122                   if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
2123                   ellipsisDestType = destType;
2124                   if(e && e.expType)
2125                   {
2126                      Type type = e.expType;
2127                      Class _class = null;
2128                      //Type destType = e.destType;
2129
2130                      if(type.kind == classType && type._class && type._class.registered)
2131                      {
2132                         _class = type._class.registered;
2133                      }
2134                      else if(type.kind == subClassType)
2135                      {
2136                         _class = FindClass("ecere::com::Class").registered;
2137                      }
2138                      else if((type.kind == arrayType || type.kind == pointerType) && type.type && type.type.kind == charType)
2139                      {
2140                         _class = FindClass("char *").registered;
2141                      }
2142                      else if(type.kind == pointerType)
2143                      {
2144                         _class = eSystem_FindClass(privateModule, "uintptr");
2145                         FreeType(e.expType);
2146                         e.expType = ProcessTypeString("uintptr", false);
2147                         // Assume null pointers means 'no object' rather than an object holding a null pointer
2148                         e.byReference = true;
2149                      }
2150                      else
2151                      {
2152                         char string[1024] = "";
2153                         Symbol classSym;
2154                         PrintTypeNoConst(type, string, false, true);
2155                         classSym = FindClass(string);
2156                         if(classSym) _class = classSym.registered;
2157                         // if(!class) _class = eSystem_FindClass(privateModule, "int");
2158                      }
2159
2160                      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...
2161                         (!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))) ||
2162                         destType.byReference)))
2163                      {
2164                         //if(!_class || strcmp(_class.fullName, "String"))     // TESTING THIS WITH NEW String class...
2165                         //if(!_class || strcmp(_class.fullName, "char *"))     // TESTING THIS WITH NEW String class...
2166                         // TESTING WITHOUT THE ABOVE NOW!
2167                         {
2168                            Expression checkedExp;
2169                            Expression parentExp;
2170                            Expression newExp;
2171
2172                            checkedExp = e;
2173                            parentExp = exp;
2174                            while(checkedExp && (((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp))
2175                            {
2176                               parentExp = checkedExp;
2177                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
2178                               {
2179                                  if(checkedExp.type == extensionCompoundExp)
2180                                  {
2181                                     checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
2182                                  }
2183                                  else
2184                                     checkedExp = checkedExp.list->last;
2185                               }
2186                               else if(checkedExp.type == castExp)
2187                                  checkedExp = checkedExp.cast.exp;
2188                            }
2189
2190                            if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
2191                            {
2192                               /*
2193                               Expression newExp = e.op.exp2;
2194                               arguments->Insert(e.prev, newExp);
2195                               arguments->Remove(e);
2196                               e.op.exp2 = null;
2197                               FreeExpContents(e);
2198                               e = newExp;
2199                               */
2200                               newExp = checkedExp.op.exp2;
2201                               checkedExp.op.exp2 = null;
2202                               FreeExpContents(checkedExp);
2203
2204                               if(e.expType && e.expType.passAsTemplate)
2205                               {
2206                                  char size[100];
2207                                  ComputeTypeSize(e.expType);
2208                                  sprintf(size, "%d", e.expType.size);   // BOOTSTRAP FIX
2209                                  newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
2210                                     MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
2211                                        MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
2212                               }
2213
2214                               if(parentExp.type == callExp)
2215                               {
2216                                  arguments->Insert(e.prev, newExp);
2217                                  arguments->Remove(e);
2218                                  e = newExp;
2219                               }
2220                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
2221                               {
2222                                  parentExp.list->Remove(checkedExp);
2223                                  parentExp.list->Add(newExp);
2224                               }
2225                               else if(parentExp.type == castExp)
2226                               {
2227                                  // NEW CODE: BETTER WAY TO DO THIS? To prevent (double)(double *)
2228                                  if(parentExp.destType && parentExp.destType.kind == ellipsisType)
2229                                  {
2230                                     FreeTypeName(parentExp.cast.typeName);
2231                                     parentExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null));
2232                                  }
2233                                  parentExp.cast.exp = newExp;
2234                               }
2235                               else if(parentExp.type == extensionCompoundExp)
2236                               {
2237                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2238                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2239                               }
2240                               e.byReference = true;
2241
2242                               FreeType(checkedExp.expType);
2243                               FreeType(checkedExp.destType);
2244                               delete checkedExp;
2245                            }
2246                            else if((!e.byReference && (!e.expType || !e.expType.classObjectType) ) || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
2247                            {
2248                               Expression checkedExp;
2249                               Expression parentExp;
2250                               Expression newExp;
2251
2252                               {
2253                                  // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
2254                                  bool hasAddress =
2255                                     e.type == identifierExp ||
2256                                     (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
2257                                     (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
2258                                     (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
2259                                     e.type == indexExp;
2260
2261                                  if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
2262                                  {
2263                                     Context context = PushContext();
2264                                     Declarator decl;
2265                                     OldList * specs = MkList();
2266                                     char typeString[1024];
2267                                     Expression newExp { };
2268
2269                                     typeString[0] = '\0';
2270                                     *newExp = *e;
2271
2272                                     // TOCHECK: Should this read e.destType ???
2273
2274                                     if(exp.destType) exp.destType.refCount++;
2275                                     // if(exp.expType) exp.expType.refCount++;
2276                                     newExp.prev = null;
2277                                     newExp.next = null;
2278                                     newExp.expType = null;
2279
2280                                     PrintTypeNoConst(e.expType, typeString, false, true);
2281                                     decl = SpecDeclFromString(typeString, specs, null);
2282                                     newExp.destType = ProcessType(specs, decl);
2283                                     if(newExp.destType && e.expType && e.expType.passAsTemplate)
2284                                     {
2285                                        Expression nbExp = GetNonBracketsExp(newExp);
2286                                        if(nbExp.type == castExp)
2287                                        {
2288                                           // Because we're correcting this after the cast was added from the argument for loop at the beginning of this case block
2289                                           // (CheckTemplateTypes() already called), we'll revert the cast to generic uint64 template type
2290                                           FreeTypeName(nbExp.cast.typeName);
2291                                           nbExp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
2292                                        }
2293
2294                                        newExp.expType = newExp.destType;
2295                                        newExp.destType.refCount++;
2296                                        modifyPassAsTemplate(&newExp.expType, true);
2297                                     }
2298
2299                                     curContext = context;
2300                                     e.type = extensionCompoundExp;
2301
2302                                     // We need a current compound for this
2303                                     if(curCompound)
2304                                     {
2305                                        char name[100];
2306                                        OldList * stmts = MkList();
2307                                        sprintf(name, "__internalValue%03X", internalValueCounter++);
2308                                        if(!curCompound.compound.declarations)
2309                                           curCompound.compound.declarations = MkList();
2310                                        curCompound.compound.declarations->Insert(null, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null))));
2311                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', newExp))));
2312                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier(name)))));
2313                                        CheckTemplateTypes(newExp);
2314                                        e.compound = MkCompoundStmt(null, stmts);
2315                                     }
2316                                     else
2317                                        printf("libec: compiler error, curCompound is null in ApplyAnyObjectLogic\n");
2318
2319                                     /*
2320
2321                                     e.compound = MkCompoundStmt(
2322                                        MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))),
2323                                        MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
2324                                     */
2325
2326                                     e.compound.compound.context = context;
2327                                     PopContext(context);
2328                                     curContext = context.parent;
2329                                  }
2330                               }
2331
2332                               // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
2333                               checkedExp = e;
2334                               parentExp = exp;
2335                               while(checkedExp && (((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp))
2336                               {
2337                                  parentExp = checkedExp;
2338                                  if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
2339                                  {
2340                                     if(checkedExp.type == extensionCompoundExp)
2341                                     {
2342                                        checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
2343                                     }
2344                                     else
2345                                        checkedExp = checkedExp.list->last;
2346                                  }
2347                                  else if(checkedExp.type == castExp)
2348                                     checkedExp = checkedExp.cast.exp;
2349                               }
2350                               {
2351                                  Expression i;
2352                                  newExp = MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)), (i = MkExpOp(null, '&', checkedExp)));
2353                                  i.byReference = true;
2354                                  newExp.byReference = true;
2355                               }
2356                               if(parentExp.type == callExp)
2357                               {
2358                                  arguments->Insert(e.prev, newExp);
2359                                  arguments->Remove(e);
2360                                  e = newExp;
2361                               }
2362                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
2363                               {
2364                                  parentExp.list->Remove(checkedExp);
2365                                  parentExp.list->Add(newExp);
2366                               }
2367                               else if(parentExp.type == castExp)
2368                                  parentExp.cast.exp = newExp;
2369                               else if(parentExp.type == bracketsExp || parentExp.type == extensionCompoundExp)
2370                               {
2371                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2372                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2373                               }
2374                            }
2375                         }
2376                      }
2377
2378                      if(destType.classObjectType == ClassObjectType::typedObject)
2379                      {
2380                         char className[1024];
2381                         // Need the class itself here...
2382                         if(!_class && type.kind == pointerType && type.type && type.type.kind == charType)
2383                            _class = eSystem_FindClass(privateModule, "String");
2384                         if(!_class) _class = eSystem_FindClass(privateModule, "int");
2385
2386                         if(!strcmp(_class.name, "class"))
2387                         {
2388                            // Already inside a typed_object function, pass the class through
2389                            strcpy(className, "class");
2390                         }
2391                         else
2392                         {
2393                            strcpy(className, "__ecereClass_");
2394                            FullClassNameCat(className, _class.fullName, true);
2395
2396                            if(!_class.symbol)
2397                               _class.symbol = FindClass(_class.fullName);
2398
2399                            DeclareClass(curExternal, _class.symbol, className);
2400                         }
2401
2402                         if(_class.type == normalClass && destType.byReference == false && strcmp(_class.dataTypeString, "char *"))
2403                         {
2404                            // ({ Instance __internal_ClassInst = e; __internal_ClassInst ? __internal_ClassInst._class : __ecereClass_...; })
2405                            Expression c;
2406                            Context context = PushContext();
2407
2408                            // Work around to avoid repeating the BuiltInContainer just to get the type
2409                            // (a bit messy since we already transformed our expression to an extensionInitializerExp in earlier pass)
2410                            if(_class.templateClass && !strcmp(_class.templateClass.name, "Container") &&
2411                               e.list && e.list->first &&
2412                               ((Expression)e.list->first).type == castExp &&
2413                               ((Expression)e.list->first).cast.exp &&
2414                               ((Expression)e.list->first).cast.exp.type == opExp &&
2415                               ((Expression)e.list->first).cast.exp.op.op == '&' &&
2416                               ((Expression)e.list->first).cast.exp.op.exp2 &&
2417                               ((Expression)e.list->first).cast.exp.op.exp2.type == extensionInitializerExp)
2418                            {
2419                               arguments->Insert(e.prev, MkExpIdentifier(MkIdentifier(className)));
2420                            }
2421                            else
2422                            {
2423                               OldList * specs;
2424                               c = MkExpExtensionCompound(MkCompoundStmt(
2425                                     MkListOne(MkDeclaration(
2426                                        (specs = MkListOne(MkSpecifierName("Instance"))),
2427                                        MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_ClassInst")),
2428                                           MkInitializerAssignment(CopyExpression(e)))))),
2429                                     MkListOne(MkExpressionStmt(MkListOne(MkExpCondition(
2430                                        MkExpIdentifier(MkIdentifier("__internal_ClassInst")),
2431                                        MkListOne(MkExpPointer(MkExpIdentifier(MkIdentifier("__internal_ClassInst")), MkIdentifier("_class"))),
2432                                        MkExpIdentifier(MkIdentifier(className))))))));
2433                               c.compound.compound.context = context;
2434                               PopContext(context);
2435
2436                               if(type.specConst)
2437                                  specs->Insert(null, MkSpecifier(CONST));
2438
2439                               arguments->Insert(e.prev, c);
2440                            }
2441                         }
2442                         else
2443                            arguments->Insert(e.prev, MkExpIdentifier(MkIdentifier(className)));
2444                      }
2445                   }
2446                }
2447                {
2448 #ifdef _DEBUG
2449                   //char debugString[4096] = "";
2450                   //PrintExpression(e, debugString);
2451 #endif
2452                   // If expression type is a simple class, make it an address
2453                   FixReference(e, !destType || !destType.declaredWithStruct);
2454                }
2455             }
2456             if(ellipsisDestType)
2457             {
2458                if(usedEllipsis ||
2459                   (expCallExp.expType && expCallExp.expType.kind == functionType && expCallExp.expType.params.last &&
2460                    ((Type)expCallExp.expType.params.last).kind == ellipsisType))
2461                {
2462                   arguments->Insert(arguments->last, MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null),null)),MkExpConstant("0")));
2463                }
2464             }
2465          }
2466
2467          if(handleNullVMethod)
2468          {
2469             Expression compoundExp;
2470             Context context = PushContext();
2471             OldList * declList = MkList();
2472             OldList * stmtList = MkList();
2473             TypeName castTypeName;
2474             OldList * specs = MkList();
2475             Specifier spec;
2476
2477             for(spec = typeName.qualifiers ? typeName.qualifiers->first : null; spec; spec = spec.next)
2478             {
2479                if(spec.type != extendedSpecifier)
2480                   specs->Add(CopySpecifier(spec));
2481             }
2482
2483             if(typeName.declarator.type == pointerDeclarator)
2484             {
2485                Pointer p = typeName.declarator.pointer.pointer.pointer;
2486                castTypeName = MkTypeName(specs, CopyDeclarator(typeName.declarator.declarator.declarator.declarator));
2487                while(p)
2488                {
2489                   Pointer pp;
2490                   for(pp = castTypeName.declarator.pointer.pointer; pp.pointer; pp = pp.pointer);
2491                   pp.pointer = MkPointer(null, null);
2492                   pp.qualifiers = CopyList(p.qualifiers, CopySpecifier);
2493                   p = p.pointer;
2494                }
2495             }
2496             else
2497                castTypeName = MkTypeName(specs, CopyDeclarator(typeName.declarator.declarator.declarator.declarator));
2498
2499             compoundExp = MkExpExtensionCompound(MkCompoundStmt(declList, stmtList));
2500
2501             declList->Add(MkDeclaration(CopyList(typeName.qualifiers, CopySpecifier),
2502                MkListOne(MkInitDeclarator(PlugDeclarator(CopyDeclarator(typeName.declarator), MkDeclaratorIdentifier(MkIdentifier("__internal_VirtualMethod"))), null))));
2503
2504             stmtList->Add(MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier("__internal_VirtualMethod")), '=', expCallExp))));
2505             stmtList->Add(MkExpressionStmt(MkListOne(MkExpCondition(
2506                MkExpIdentifier(MkIdentifier("__internal_VirtualMethod")),
2507                MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("__internal_VirtualMethod")), arguments)), MkExpCast(castTypeName, MkExpConstant("1"))))));
2508
2509             compoundExp.loc = exp.loc;
2510             compoundExp.compound.compound.context = context;
2511             PopContext(context);
2512
2513             exp.type = bracketsExp;
2514             exp.list = MkListOne(compoundExp);
2515          }
2516          else
2517          {
2518             exp.call.exp = expCallExp;
2519             exp.call.arguments = arguments;
2520          }
2521          break;
2522       }
2523       case memberExp:
2524       {
2525          bool changeToPtr = false;
2526          bool noHead = false;
2527          Type type = exp.member.exp ? exp.member.exp.expType : null;
2528          Specifier memberClassSpecifier = exp.member.member ? exp.member.member._class : null;
2529          if(exp.member.member) exp.member.member._class = null;
2530
2531          if(type && type.kind == templateType)
2532          {
2533             Type baseType = ProcessTemplateParameterType(type.templateParameter);
2534             if(baseType) type = baseType;
2535          }
2536          if(type && exp.member.member && !type.directClassAccess)
2537          {
2538             Class _class = exp.member.member.classSym ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
2539             Property prop = null;
2540             ClassProperty classProperty = null;
2541             Method method = null;
2542             Class convertTo = null;
2543             DataMember member = null;
2544             DataMember subMemberStack[256];
2545             int subMemberStackPos = 0;
2546             bool thisPtr = exp.member.thisPtr;
2547             if(type.kind == subClassType && exp.member.exp.type == classExp)
2548                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
2549
2550             // TEST: exp.member.exp.tempCount = Max(exp.tempCount, exp.member.exp.tempCount);
2551
2552             if(!_class)
2553             {
2554                // DANGER: Buffer overflow
2555                char string[2048] = "";
2556                Symbol classSym;
2557                PrintTypeNoConst(type, string, false, true);
2558                classSym = FindClass(string);
2559                _class = classSym ? classSym.registered : null;
2560             }
2561
2562             if(_class && exp.member.memberType == dataMember)
2563             {
2564                if(!thisPtr && !exp.member.member.classSym)
2565                   member = eClass_FindDataMember(_class, exp.member.member.string, null, subMemberStack, &subMemberStackPos);
2566                if(!member)
2567                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, subMemberStack, &subMemberStackPos);
2568             }
2569             else if(_class && exp.member.memberType == propertyMember)
2570             {
2571                if(!thisPtr && !exp.member.member.classSym)
2572                   prop = eClass_FindProperty(_class, exp.member.member.string, null);
2573                if(!prop)
2574                   prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
2575                if(prop && (exp.usage.usageRef ||
2576                   (exp.usage.usageGet && !prop.Get && !prop.conversion) ||
2577                   (exp.usage.usageDelete && !prop.Set && !prop.conversion)))
2578                {
2579                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, subMemberStack, &subMemberStackPos);
2580                   if(member)
2581                   {
2582                      exp.member.memberType = dataMember;
2583                      prop = null;
2584                   }
2585                   else
2586                   {
2587                      if(exp.usage.usageRef)
2588                         Compiler_Error($"cannot obtain address of property\n");
2589                      else if(!prop.Get)
2590                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2591                      else if(exp.usage.usageDelete)
2592                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2593                   }
2594                }
2595             }
2596             else if(_class && exp.member.memberType == methodMember)
2597             {
2598                if(!thisPtr)
2599                   method = eClass_FindMethod(_class, exp.member.member.string, null);
2600                if(!method)
2601                   method = eClass_FindMethod(_class, exp.member.member.string, privateModule);
2602             }
2603             else if(_class && exp.member.memberType == reverseConversionMember)
2604             {
2605                convertTo = _class;
2606                _class = FindClass(exp.member.member.string).registered;
2607                // prop = eClass_FindProperty(_class, convertTo.name, privateModule);
2608                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
2609             }
2610             else if(_class && exp.member.memberType == classPropertyMember)
2611             {
2612                classProperty = eClass_FindClassProperty(_class, exp.member.member.string);
2613             }
2614             if(prop)
2615             {
2616                // Only process Gets here, Set is processed in opExp's '='
2617                if(exp.usage.usageGet)
2618                {
2619                   if(prop.Get)
2620                   {
2621                      char getName[1024], setName[1024];
2622                      Expression ptr = exp.member.exp;
2623                      Class propertyClass;
2624                      char * nameToUse = convertTo ? setName : getName;
2625
2626                      FreeIdentifier(exp.member.member);
2627
2628                      // Process this here since it won't be processed at the end...
2629                      exp.member.exp.usage.usageGet = true;
2630                      ProcessExpression(exp.member.exp);
2631                      // TEST: exp.tempCount = exp.member.exp.tempCount;
2632
2633                      DeclareProperty(curExternal, prop, setName, getName);
2634                      //propertyClass = convertTo ? _class : ((Symbol)prop.symbol)._class;
2635                      propertyClass = convertTo ? _class :
2636                         ((((Symbol)prop.symbol).type && ((Symbol)prop.symbol).type.kind == classType) ? ((Symbol)prop.symbol).type._class.registered : ((Symbol)prop.symbol)._class);
2637
2638                      if(propertyClass && propertyClass.type == bitClass)
2639                      {
2640                         // Bit classes shouldn't have properties except for conversions...
2641                         OldList * args = MkList();
2642                         if(exp.usage.usageDeepGet)
2643                         {
2644                            char className[1024];
2645                            Declaration decl;
2646                            Declarator declarator;
2647                            OldList * specs = MkList(), * decls = MkList();
2648                            Expression tempExp;
2649
2650                            // Make a declaration in the closest compound statement
2651                            // (Do not reuse (since using address for function calls)...)
2652                            sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2653                            declarator =
2654                               SpecDeclFromString(propertyClass.dataTypeString, specs,
2655                                  MkDeclaratorIdentifier(MkIdentifier(className)));
2656
2657                            ListAdd(decls, MkInitDeclarator(declarator, null));
2658
2659                            decl = MkDeclaration(specs, decls);
2660                            if(!curCompound.compound.declarations)
2661                               curCompound.compound.declarations = MkList();
2662                            curCompound.compound.declarations->Insert(null, decl);
2663
2664                            tempExp = QMkExpId(className);
2665                            tempExp.expType = MkClassType(propertyClass.fullName);
2666
2667                            exp.op.exp1 = tempExp;
2668                            exp.op.exp2 = MkExpCall(QMkExpId(nameToUse), args);
2669                            exp.op.op = '=';
2670                            exp.type = opExp;
2671                         }
2672                         else
2673                         {
2674                            exp.type = callExp;
2675                            exp.call.exp = QMkExpId(nameToUse);
2676                            exp.call.arguments = args;
2677                         }
2678                         ListAdd(args, FixReference(ptr, true));
2679                      }
2680                      else if(propertyClass && propertyClass.type == unitClass)
2681                      {
2682                         OldList * args = MkList();
2683                         ListAdd(args, FixReference(ptr, true));
2684                         exp.type = callExp;
2685                         exp.call.exp = QMkExpId(nameToUse);
2686                         exp.call.arguments = args;
2687                      }
2688                      else if(propertyClass && propertyClass.type == structClass)
2689                      {
2690                         OldList * args = MkList();
2691                         char className[1024];
2692                         Declaration decl;
2693                         OldList * specs = MkList(), * decls = MkList();
2694                         Expression tempExp;
2695
2696                         // Make a declaration in the closest compound statement
2697                         // (Do not reuse (since using address for function calls)...)
2698
2699                         className[0] = 0;
2700                         FullClassNameCat(className, propertyClass.fullName, false); //true);
2701                         DeclareStruct(curExternal, propertyClass.fullName, false, true);
2702
2703                         //ListAdd(specs, MkSpecifierName(className));
2704                         ListAdd(specs, MkStructOrUnion(structSpecifier, MkIdentifier(className), null));
2705
2706                         sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2707
2708                         ListAdd(decls, MkInitDeclarator(
2709                            MkDeclaratorIdentifier(MkIdentifier(className)), null));
2710
2711                         decl = MkDeclaration(specs, decls);
2712                         if(curCompound)
2713                         {
2714                            if(!curCompound.compound.declarations)
2715                               curCompound.compound.declarations = MkList();
2716                            curCompound.compound.declarations->Insert(null, decl);
2717                         }
2718
2719                         tempExp = QMkExpId(className);
2720                         tempExp.expType = MkClassType(propertyClass.fullName);
2721
2722                         if(convertTo)
2723                         {
2724                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2725                            ListAdd(args, FixReference(ptr, true));
2726                         }
2727                         else
2728                         {
2729                            ListAdd(args, FixReference(ptr, true));
2730                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2731                         }
2732
2733                         if(exp.usage.usageDeepGet)
2734                         {
2735                            exp.type = callExp;
2736                            exp.call.exp = QMkExpId(nameToUse);
2737                            exp.call.arguments = args;
2738
2739                            FreeExpression(tempExp);
2740                         }
2741                         else
2742                         {
2743                            exp.type = bracketsExp;
2744                            exp.list = MkList();
2745                            ListAdd(exp.list, MkExpCall(QMkExpId(nameToUse),args));
2746                            if(exp.usage.usageMember)
2747                            {
2748                               ListAdd(exp.list, FixReference(tempExp, true));
2749                               exp.byReference = true;
2750                            }
2751                            else
2752                               ListAdd(exp.list, tempExp);
2753                         }
2754                      }
2755                      else
2756                      {
2757                         exp.type = callExp;
2758                         exp.call.exp = QMkExpId(nameToUse);
2759                         exp.call.arguments = MkList();
2760                         ListAdd(exp.call.arguments, FixReference(ptr, true));
2761                      }
2762                   }
2763                   else if(prop.conversion)
2764                   {
2765                      void * prev = exp.prev, * next = exp.next;
2766                      *exp = *exp.member.exp;
2767                      exp.prev = prev;
2768                      exp.next = next;
2769                   }
2770                }
2771             }
2772             else if(classProperty)
2773             {
2774                // Only process Gets here, Set is processed in opExp's '='
2775                if(exp.usage.usageGet)
2776                {
2777                   if(classProperty.Get)
2778                   {
2779                      Identifier id = exp.member.member;
2780                      Expression classExp = exp.member.exp;
2781                      OldList * args = MkList();
2782
2783                      exp.type = castExp;
2784                      // Class Property
2785                      if(exp.expType)
2786                      {
2787                         char typeString[2048];
2788                         OldList * specs = MkList();
2789                         Declarator decl;
2790                         typeString[0] = 0;
2791                         PrintType(exp.expType, typeString, false, false);
2792                         decl = SpecDeclFromString(typeString, specs, null);
2793                         exp.cast.typeName = MkTypeName(specs, decl);
2794                      }
2795                      else
2796                         exp.cast.typeName = QMkType("uint64", null);
2797                      exp.cast.exp = MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eClass_GetProperty")), args);
2798                      if(exp.expType.isPointerType)
2799                         exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
2800
2801                      ListAdd(args, classExp);
2802                      {
2803                         char * s = QMkString(id.string);
2804                         ListAdd(args, MkExpString(s));
2805                         delete s;
2806                      }
2807                      FreeIdentifier(id);
2808
2809                      ProcessExpression(exp);
2810                      return;
2811                   }
2812                }
2813             }
2814             else if(method)
2815             {
2816                // Get the function address if it's not called
2817                if((exp.usage.usageGet || exp.member.exp.expType.kind == subClassType) && !(exp.usage.usageCall))
2818                {
2819                   char name[1024];
2820
2821                   FreeIdentifier(exp.member.member);
2822
2823                   // Process this here since it won't be processed at the end...
2824                   exp.member.exp.usage.usageGet = true;
2825                   ProcessExpression(exp.member.exp);
2826                   // TEST: exp.tempCount = exp.member.exp.tempCount;
2827
2828                   if(method.type == virtualMethod)
2829                   {
2830                      strcpy(name, "__ecereVMethodID_");
2831                      FullClassNameCat(name, method._class.fullName, false);
2832                      strcat(name, "_");
2833                      strcat(name, method.name);
2834                      exp.type = indexExp;
2835                      if(memberClassSpecifier)
2836                      {
2837                         char className[1024];
2838                         // Need the class itself here...
2839                         strcpy(className, "__ecereClass_");
2840                         FullClassNameCat(className, _class.fullName, true);
2841
2842                         if(!_class.symbol)
2843                            _class.symbol = FindClass(_class.fullName);
2844                         DeclareClass(curExternal, _class.symbol, className);
2845
2846                         FreeExpression(exp.member.exp);
2847                         exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl"));
2848                      }
2849                      else
2850                      {
2851                         if(exp.thisPtr && _class.type != normalClass)
2852                         {
2853                            FreeExpression(exp.member.exp);
2854                            exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("_vTbl"));
2855                         }
2856                         else
2857                            exp.index.exp = MkExpPointer(exp.member.exp, MkIdentifier("_vTbl"));
2858                      }
2859                      exp.index.index = MkListOne(QMkExpId(name));
2860                      DeclareMethod(curExternal, method, name);
2861                   }
2862                   else
2863                   {
2864                      FreeExpression(exp.member.exp);
2865                      exp.type = identifierExp;
2866                      strcpy(name, "__ecereMethod_");
2867                      FullClassNameCat(name, method._class.fullName, false);
2868                      strcat(name, "_");
2869                      strcat(name, method.name);
2870                      exp.identifier = MkIdentifier(name);
2871                      DeclareMethod(curExternal, method, name);
2872                   }
2873                }
2874             }
2875             else if(member)
2876             {
2877                if(subMemberStackPos)
2878                {
2879                   int i;
2880                   DataMember parentMember = null;
2881                   String s, prefix = null;
2882                   for(i = 0; i < subMemberStackPos; i++)
2883                   {
2884                      DataMember curMember = subMemberStack[i];
2885                      DataMember m;
2886                      int anonID = 1;
2887                      for(m = parentMember ? parentMember.members.first : _class.membersAndProperties.first; m; m = m.next)
2888                      {
2889                         if(m && !m.isProperty && (m.type == unionMember || m.type == structMember) && !m.name)
2890                         {
2891                            if(m == curMember)
2892                               break;
2893                            anonID++;
2894                         }
2895                      }
2896
2897                      if(prefix)
2898                      {
2899                         s = prefix;
2900                         prefix = PrintString(prefix, ".__anon", anonID);
2901                         delete s;
2902                      }
2903                      else
2904                         prefix = PrintString("__anon", anonID);
2905                      parentMember = curMember;
2906                   }
2907
2908                   s = exp.member.member.string;
2909                   exp.member.member.string = PrintString(prefix, ".", s);
2910                   delete prefix;
2911                   delete s;
2912                }
2913                // Process this here since it won't be processed at the end...
2914                if(exp.usage.usageGet)
2915                {
2916                   exp.member.exp.usage.usageGet = true;   // Recently added this... is it ok?
2917                }
2918                ProcessExpression(exp.member.exp);
2919                // TEST: exp.tempCount = exp.member.exp.tempCount;
2920
2921                if(type.kind == classType && type._class && type._class.registered)
2922                   DeclareStruct(curExternal, type._class.registered.fullName, false, true);
2923
2924                // TESTING THIS NOHEAD STUFF...
2925                if(_class.type == noHeadClass)
2926                {
2927                   noHead = true;
2928                }
2929                else if(_class.type == structClass)
2930                {
2931                   changeToPtr = true;
2932                }
2933                else if(_class.type == bitClass)
2934                {
2935                   OldList * list = MkList();
2936                   char mask[32], shift[10];
2937                   OldList * specs = MkList();
2938                   BitMember bitMember = (BitMember) member;
2939                   Declarator decl = SpecDeclFromString(bitMember.dataTypeString, specs, null);
2940                   TypeName type = MkTypeName(specs, decl);
2941                   if(bitMember.mask > MAXDWORD)
2942                      sprintf(mask, FORMAT64HEXLL, bitMember.mask);
2943                   else
2944                      sprintf(mask, FORMAT64HEX, bitMember.mask);
2945                   sprintf(shift, "%d", bitMember.pos);
2946
2947                   FreeIdentifier(exp.member.member);
2948
2949                   // ((type) ((color & mask) >> bitPos))
2950                   ListAdd(list, MkExpCast(type, MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(MkListOne(
2951                      MkExpOp(exp.member.exp, '&', MkExpConstant(mask)))), RIGHT_OP,
2952                         MkExpConstant(shift))))));
2953
2954                   exp.type = bracketsExp;
2955                   exp.list = list;
2956                }
2957                else if(_class.type == unitClass)
2958                {
2959                }
2960                else
2961                {
2962                   // If it's a this pointer, replace by precomputed shortcut
2963                   if(exp.member.exp.type == identifierExp && thisPtr && type.kind == classType && (!exp.member.exp.expType || !exp.member.exp.expType.typedByReference))
2964                   {
2965                      char pointerName[1024];
2966
2967                      strcpy(pointerName, "__ecerePointer_");
2968                      FullClassNameCat(pointerName, type._class.registered.fullName, false);
2969                      if(exp.member.exp.identifier)
2970                         FreeIdentifier(exp.member.exp.identifier);
2971                      exp.member.exp.identifier = MkIdentifier(pointerName);
2972                   }
2973                   // Otherwise, access the data the hard way
2974                   else
2975                   {
2976                      Expression bytePtr, e;
2977                      Expression checkedExp;
2978                      char structName[1024];
2979                      char className[1024];
2980                      strcpy(className, "__ecereClass_");
2981                      FullClassNameCat(className, member._class.fullName, true);
2982
2983                      // classExp = QMkExpId(className);
2984
2985                      if(!member._class.symbol)
2986                         member._class.symbol = FindClass(member._class.fullName);
2987
2988                      DeclareClass(curExternal, member._class.symbol, className);
2989                      DeclareStruct(curExternal, member._class.fullName, false, true);
2990
2991                      structName[0] = 0;
2992                      FullClassNameCat(structName, member._class.fullName, false);
2993
2994                      checkedExp = exp.member.exp;
2995                      while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list && checkedExp.list->count == 1) ||
2996                            checkedExp.type == castExp)
2997                      {
2998                         if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
2999                            checkedExp = checkedExp.list->last;
3000                         else if(checkedExp.type == castExp)
3001                            checkedExp = checkedExp.cast.exp;
3002                      }
3003
3004                      if(checkedExp.type != identifierExp &&
3005                         checkedExp.type != constantExp &&      // Added this here... Might mess up if we need address?
3006                         checkedExp.type != memberExp && checkedExp.type != pointerExp)
3007                      {
3008                         char ecereTemp[100];
3009                         Statement compound;
3010                         Context context = PushContext();
3011                         if(exp.member.exp.tempCount > exp.tempCount)
3012                            exp.tempCount = exp.member.exp.tempCount;
3013
3014                         exp.tempCount++;
3015                         curExternal.function.tempCount = Max(curExternal.function.tempCount, exp.tempCount);
3016                         sprintf(ecereTemp, "__ecTemp%d", exp.tempCount);
3017                         curContext = context;
3018                         compound = MkCompoundStmt(
3019                            MkListOne(MkDeclaration(MkListOne(MkSpecifier(CHAR)), MkListOne(MkInitDeclarator(
3020                               MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier(ecereTemp))),
3021                                  MkInitializerAssignment(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)), QBrackets(exp.member.exp))))))), null);
3022                         if(member._class.fixed)
3023                         {
3024                            Class c = member._class.templateClass ? member._class.templateClass : member._class;
3025                            if(c.offset)
3026                            {
3027                               Expression se;
3028
3029                               if(c.offset == c.base.structSize)
3030                               {
3031                                  se = MkExpClassSize(MkSpecifierName(c.base.fullName));
3032                                  ProcessExpressionType(se);
3033                                  se.isConstant = false;
3034                               }
3035                               else
3036                               {
3037                                  char string[256];
3038                                  sprintf(string, "%d", c.offset);
3039                                  se = MkExpConstant(string);
3040                               }
3041                               e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', se));
3042                            }
3043                            else
3044                               e = QMkExpId(ecereTemp);
3045                         }
3046                         else
3047                         {
3048                            e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+',
3049                               MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
3050                         }
3051
3052                         compound.compound.context = context;
3053                         compound.compound.statements = MkListOne(MkExpressionStmt(MkListOne(
3054                            QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
3055                               MkDeclaratorPointer(MkPointer(null, null), null)), e)))));
3056
3057                         exp.member.exp =  MkExpExtensionCompound(compound);
3058
3059                         PopContext(context);
3060                         curContext = context.parent;
3061                      }
3062                      else
3063                      {
3064                         bytePtr = MkExpCast(QMkType("char", QMkPtrDecl(null)), /*CopyExpression(*/exp.member.exp/*)*/);
3065                         // DISABLED BECAUSE PREVENTS GETTING ADDRESS OF MEMBERS WITH ADDRESS 0
3066                         /*
3067                         e = QBrackets(QMkExpCond(exp.member.exp,
3068                            QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(classExp, MkIdentifier("offset")))),
3069                            MkExpConstant("0")));
3070                         */
3071
3072                         // if(class.fixed)
3073                         if(member._class.fixed)
3074                         {
3075                            Class c = member._class.templateClass ? member._class.templateClass : member._class;
3076                            if(c.offset)
3077                            {
3078                               Expression se;
3079
3080                               if(c.offset == c.base.structSize)
3081                               {
3082                                  se = MkExpClassSize(MkSpecifierName(c.base.fullName));
3083                                  ProcessExpressionType(se);
3084                                  se.isConstant = false;
3085                               }
3086                               else
3087                               {
3088                                  char string[256];
3089                                  sprintf(string, "%d", c.offset);
3090                                  se = MkExpConstant(string);
3091                               }
3092
3093                               e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', se)));
3094                            }
3095                            else
3096                               e = bytePtr;
3097                         }
3098                         else
3099                            e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(QMkExpId(className), MkIdentifier("offset")))));
3100
3101                         // exp.member.exp = QBrackets(MkExpCast(QMkType(structName, QMkPtrDecl(null)), e));
3102                         exp.member.exp = QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), QMkPtrDecl(null)), e));
3103                      }
3104                   }
3105                   exp.type = pointerExp;
3106                }
3107             }
3108          }
3109
3110          // Take Out Any Class Specifier (Should have been used by now)
3111          FreeSpecifier(memberClassSpecifier);
3112
3113          // Just moved this at the end... How is it?
3114          if(exp.member.exp && (exp.type == memberExp || exp.type == pointerExp))
3115          {
3116             exp.member.exp.usage.usageGet = true;
3117             exp.member.exp.usage.usageMember = true;
3118             exp.member.exp.tempCount = exp.tempCount;
3119             ProcessExpression(exp.member.exp);
3120             exp.tempCount = exp.member.exp.tempCount;
3121             if((changeToPtr && exp.member.exp.byReference) || noHead)
3122                exp.type = pointerExp;
3123          }
3124          break;
3125       }
3126       case extensionCompoundExp:
3127       {
3128          Expression e = ((Statement)exp.compound.compound.statements->last).expressions->last;
3129          if(e)
3130             e.usage |= exp.usage & ExpUsage { usageGet = true, usageArg = true, usageMember = true };
3131
3132          ProcessStatement(exp.compound);
3133
3134          /*if(((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference)
3135             exp.byReference = ((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference;*/
3136          break;
3137       }
3138       case pointerExp:
3139       {
3140          exp.member.exp.usage.usageGet = true;
3141          ProcessExpression(exp.member.exp);
3142          break;
3143       }
3144       case typeSizeExp:
3145       {
3146          Specifier spec = exp.typeName.qualifiers ? exp.typeName.qualifiers->first : null;
3147          if(spec && spec.type == templateTypeSpecifier && !exp.typeName.declarator)
3148          {
3149             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, false);
3150             if(argExp)
3151             {
3152                Expression classExp;
3153
3154                FreeTypeName(exp.typeName);
3155
3156                classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
3157
3158                ProcessExpressionType(classExp);
3159                ProcessExpression(classExp);
3160
3161                exp.type = bracketsExp;
3162                exp.list = MkListOne(MkExpMember(classExp, MkIdentifier("typeSize")));
3163
3164                ProcessExpressionType(exp);
3165                ProcessExpression(exp);
3166             }
3167          }
3168          break;
3169       }
3170       case castExp:
3171       {
3172          if(exp.cast.exp)
3173          {
3174             exp.cast.exp.usage |= exp.usage & ExpUsage { usageGet = true, usageMember = true };
3175             ProcessExpression(exp.cast.exp);
3176             // TESTING THIS
3177             if(exp.cast.exp.byReference)
3178                exp.byReference = exp.cast.exp.byReference;
3179             if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass &&
3180                exp.cast.exp.expType && (exp.cast.exp.expType.kind == pointerType || exp.cast.exp.expType.kind == arrayType || (
3181                   exp.cast.exp.expType.kind == classType && exp.cast.exp.expType._class && exp.cast.exp.expType._class.registered &&
3182                      !strcmp(exp.cast.exp.expType._class.registered.dataTypeString, "char *")) ) )
3183                exp.byReference = true;
3184          }
3185          // Moved this to 1.5...
3186          //exp.expType = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
3187          break;
3188       }
3189       case conditionExp:
3190       {
3191          Expression e;
3192          if(exp.usage.usageGet)
3193             exp.cond.cond.usage.usageGet = true;
3194          ProcessExpression(exp.cond.cond);
3195          for(e = exp.cond.exp->first; e; e = e.next)
3196          {
3197             if(!e.next && exp.usage.usageGet) e.usage.usageGet = true;
3198             ProcessExpression(e);
3199          }
3200          if(exp.usage.usageGet)
3201             exp.cond.elseExp.usage.usageGet = true;
3202          ProcessExpression(exp.cond.elseExp);
3203          break;
3204       }
3205       case classExp:
3206       {
3207          // Need the class itself here...
3208          if(exp._classExp.specifiers && exp._classExp.specifiers->first && ((Specifier)exp._classExp.specifiers->first).type == templateTypeSpecifier)
3209          {
3210             Specifier spec = exp._classExp.specifiers->first;
3211             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, true);
3212             if(argExp)
3213             {
3214                FreeList(exp._classExp.specifiers, FreeSpecifier);
3215                if(exp._classExp.decl)
3216                   FreeDeclarator(exp._classExp.decl);
3217
3218                exp.type = memberExp; //pointerExp;
3219                exp.member.exp = argExp;
3220                exp.member.member = MkIdentifier("dataTypeClass");
3221                exp.member.memberType = dataMember;
3222
3223                ProcessExpressionType(argExp);
3224                ProcessExpressionType(exp);
3225                ProcessExpression(exp);
3226             }
3227          }
3228          else
3229          {
3230             char className[1024];
3231             char * string = StringFromSpecDecl(exp._classExp.specifiers, exp._classExp.decl);
3232             Symbol classSym = FindClass(string);
3233
3234             strcpy(className, "__ecereClass_");
3235             FullClassNameCat(className, string, true);      // TODO: Verify this
3236
3237             DeclareClass(curExternal, classSym, className);
3238             delete string;
3239
3240             FreeList(exp._classExp.specifiers, FreeSpecifier);
3241             if(exp._classExp.decl)
3242                FreeDeclarator(exp._classExp.decl);
3243
3244             exp.type = identifierExp;
3245             exp.identifier = MkIdentifier(className);
3246          }
3247          break;
3248       }
3249       case vaArgExp:
3250       {
3251          ProcessExpression(exp.vaArg.exp);
3252          break;
3253       }
3254       case extensionInitializerExp:
3255       {
3256          ProcessInitializer(exp.initializer.initializer);
3257          break;
3258       }
3259    }
3260    FixRefExp(exp);
3261
3262    if(exp.needTemplateCast != 2 && (exp.needTemplateCast == 1 || (exp.expType && (exp.expType.kind == templateType || exp.expType.passAsTemplate))))
3263    {
3264       Expression nbExp = GetNonBracketsExp(exp);
3265       Expression inner = GetInnerExp(nbExp);
3266
3267       if((!exp.expType || exp.expType.kind != templateType || nbExp.type != castExp) && !exp.usage.usageRef &&
3268          (!exp.destType || (!exp.destType.truth && (exp.destType.kind != templateType || (exp.destType.templateParameter && (exp.destType.templateParameter.dataTypeString || exp.destType.templateParameter.dataType))))) &&
3269          (exp.usage.usageDelete || exp.usage.usageGet || exp.usage.usageArg) &&
3270          (!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))) &&
3271          !inner.needCast && inner.type != opExp)
3272       {
3273          Expression e = MoveExpContents(exp);
3274          Declarator decl;
3275          OldList * specs = MkList();
3276          char typeString[1024];
3277          bool castingToDest = false;
3278          bool pointerCastExp = false;
3279
3280          typeString[0] = '\0';
3281
3282          e.needTemplateCast = 2;
3283          inner.needTemplateCast = 2;
3284          nbExp.needTemplateCast = 2;
3285          if(exp.usage.usageDelete)
3286             strcpy(typeString, "void *");
3287          else
3288          {
3289             if(exp.expType.kind == templateType && exp.expType.templateParameter && exp.expType.templateParameter.dataTypeString)
3290                strcpy(typeString, exp.expType.templateParameter.dataTypeString);
3291             else
3292                PrintType(exp.expType, typeString, false, false);
3293          }
3294
3295          decl = SpecDeclFromString(typeString, specs, null);
3296
3297          if(specs && specs->first && ((Specifier)specs->first).type == templateTypeSpecifier &&
3298             exp.destType && !exp.destType.passAsTemplate && exp.destType.kind == templateType && exp.destType.templateParameter && (exp.destType.templateParameter.dataTypeString || exp.destType.templateParameter.dataType) && !exp.usage.usageArg)
3299          {
3300             if(decl) FreeDeclarator(decl);
3301             FreeList(specs, FreeSpecifier);
3302             if(exp.destType.templateParameter.dataTypeString)
3303             {
3304                specs = MkList();
3305                strcpy(typeString, exp.destType.templateParameter.dataTypeString);
3306                decl = SpecDeclFromString(typeString, specs, null);
3307             }
3308             else
3309             {
3310                specs = CopyList(exp.destType.templateParameter.dataType.specifiers, CopySpecifier);
3311                decl = CopyDeclarator(exp.destType.templateParameter.dataType.decl);
3312             }
3313
3314             castingToDest = true;
3315          }
3316
3317          e.destType = exp.destType;
3318          if(exp.destType)
3319             exp.destType.refCount++;
3320
3321          exp.type = bracketsExp;
3322
3323          {
3324             Specifier spec = specs ? specs->first : null;
3325             TemplateParameter tp = (spec && spec.type == templateTypeSpecifier) ? spec.templateParameter : null;
3326             Type type = castingToDest ? exp.destType : exp.expType;
3327             bool specsDeclPointer = (spec.type == nameSpecifier && strcmp(spec.name, "uint64")) ||
3328                (decl && decl.type == pointerDeclarator) ||
3329                (tp && tp.dataType &&
3330                   ( (tp.dataType.decl && tp.dataType.decl.type == pointerDeclarator) ||
3331                     (tp.dataType.specifiers && ((Specifier)tp.dataType.specifiers->first).type == nameSpecifier && strcmp(((Specifier)tp.dataType.specifiers->first).name, "uint64")) ) );
3332             pointerCastExp = type ? ((type.kind == templateType && specsDeclPointer) || type.isPointerType) : specsDeclPointer;
3333          }
3334
3335          if(pointerCastExp)
3336          {
3337             e = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), MkExpBrackets(MkListOne(e)));
3338             e.needTemplateCast = 2;
3339          }
3340          exp.list = MkListOne(MkExpCast(MkTypeName(specs, decl), MkExpBrackets(MkListOne(e))));
3341          if(exp.destType && pointerCastExp == (exp.destType.passAsTemplate ||
3342             (!exp.destType.isPointerType || (exp.destType.kind == templateType && (!exp.destType.templateParameter || (!exp.destType.templateParameter.dataType && !exp.destType.templateParameter.dataTypeString))))))
3343             exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), decl), MkExpBrackets(exp.list)));
3344          exp.needTemplateCast = 2;
3345       }
3346    }
3347    yylloc = oldyylloc;
3348 }
3349
3350 static void ProcessInitializer(Initializer init)
3351 {
3352    switch(init.type)
3353    {
3354       case expInitializer:
3355          if(init.exp)
3356          {
3357             init.exp.usage.usageGet = true;
3358             ProcessExpression(init.exp);
3359             if(init.exp.destType && init.exp.destType.kind == classType && init.exp.destType._class &&
3360                init.exp.destType._class.registered && init.exp.destType._class.registered.type == noHeadClass)
3361             {
3362                FixReference(init.exp, true);
3363             }
3364             else if(init.exp.destType && init.exp.destType.kind == classType)
3365                FixReference(init.exp, false);
3366          }
3367          break;
3368       case listInitializer:
3369       {
3370          if(init.list)
3371          {
3372             Initializer i;
3373             for(i = init.list->first; i; i = i.next)
3374                ProcessInitializer(i);
3375          }
3376          break;
3377       }
3378    }
3379 }
3380
3381 static void ProcessDeclaration(Declaration decl)
3382 {
3383    switch(decl.type)
3384    {
3385       case initDeclaration:
3386       {
3387          if(decl.declarators)
3388          {
3389             InitDeclarator d;
3390
3391             for(d = decl.declarators->first; d; d = d.next)
3392             {
3393                if(d.initializer)
3394                   ProcessInitializer(d.initializer);
3395             }
3396          }
3397          break;
3398       }
3399    }
3400 }
3401
3402 static void ProcessStatement(Statement stmt)
3403 {
3404    switch(stmt.type)
3405    {
3406       case labeledStmt:
3407          ProcessStatement(stmt.labeled.stmt);
3408          break;
3409       case caseStmt:
3410          if(stmt.caseStmt.exp)
3411          {
3412             stmt.caseStmt.exp.usage.usageGet = true;
3413
3414             // This expression should be constant...
3415             ProcessExpression(stmt.caseStmt.exp);
3416          }
3417          if(stmt.caseStmt.stmt)
3418             ProcessStatement(stmt.caseStmt.stmt);
3419          break;
3420       case compoundStmt:
3421       {
3422          if(stmt.compound.context)
3423          {
3424             Declaration decl;
3425             Statement s;
3426             Statement prevCompound = curCompound;
3427             Context prevContext = curContext;
3428
3429             if(!stmt.compound.isSwitch)
3430             {
3431                curCompound = stmt;
3432                curContext = stmt.compound.context;
3433             }
3434
3435             if(stmt.compound.declarations)
3436             {
3437                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
3438                   ProcessDeclaration(decl);
3439             }
3440             if(stmt.compound.statements)
3441             {
3442                for(s = stmt.compound.statements->first; s; s = s.next)
3443                   ProcessStatement(s);
3444             }
3445             curContext = prevContext;
3446             curCompound = prevCompound;
3447          }
3448          break;
3449       }
3450       case expressionStmt:
3451       {
3452          Expression exp;
3453          if(stmt.expressions)
3454          {
3455             for(exp = stmt.expressions->first; exp; exp = exp.next)
3456             {
3457                ProcessExpression(exp);
3458             }
3459          }
3460          break;
3461       }
3462       case ifStmt:
3463       {
3464          if(stmt.ifStmt.exp)
3465          {
3466             Expression exp;
3467
3468             ((Expression)stmt.ifStmt.exp->last).usage.usageGet = true;
3469             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
3470             {
3471                ProcessExpression(exp);
3472             }
3473          }
3474          if(stmt.ifStmt.stmt)
3475             ProcessStatement(stmt.ifStmt.stmt);
3476          if(stmt.ifStmt.elseStmt)
3477             ProcessStatement(stmt.ifStmt.elseStmt);
3478          break;
3479       }
3480       case switchStmt:
3481       {
3482          Expression exp;
3483          if(stmt.switchStmt.exp && stmt.switchStmt.exp->last)
3484          {
3485             ((Expression)stmt.switchStmt.exp->last).usage.usageGet = true;
3486             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
3487             {
3488                ProcessExpression(exp);
3489             }
3490          }
3491          ProcessStatement(stmt.switchStmt.stmt);
3492          break;
3493       }
3494       case whileStmt:
3495       {
3496          Expression exp;
3497          if(stmt.whileStmt.exp && stmt.whileStmt.exp->last)
3498          {
3499             ((Expression)stmt.whileStmt.exp->last).usage.usageGet = true;
3500             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
3501             {
3502                ProcessExpression(exp);
3503             }
3504          }
3505          ProcessStatement(stmt.whileStmt.stmt);
3506          break;
3507       }
3508       case doWhileStmt:
3509       {
3510          Expression exp;
3511          if(stmt.doWhile.exp && stmt.doWhile.exp->last)
3512          {
3513             ((Expression)stmt.doWhile.exp->last).usage.usageGet = true;
3514             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
3515             {
3516                ProcessExpression(exp);
3517             }
3518          }
3519          if(stmt.doWhile.stmt)
3520             ProcessStatement(stmt.doWhile.stmt);
3521          break;
3522       }
3523       case forStmt:
3524       {
3525          Expression exp;
3526          if(stmt.forStmt.init)
3527             ProcessStatement(stmt.forStmt.init);
3528
3529          if(stmt.forStmt.check)
3530          {
3531             if(stmt.forStmt.check.expressions)
3532             {
3533                ((Expression)stmt.forStmt.check.expressions->last).usage.usageGet = true;
3534             }
3535             ProcessStatement(stmt.forStmt.check);
3536          }
3537          if(stmt.forStmt.increment)
3538          {
3539             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
3540             {
3541                ProcessExpression(exp);
3542             }
3543          }
3544          if(stmt.forStmt.stmt)
3545             ProcessStatement(stmt.forStmt.stmt);
3546          break;
3547       }
3548       case gotoStmt:
3549          break;
3550       case continueStmt:
3551          break;
3552       case breakStmt:
3553          break;
3554       case returnStmt:
3555       {
3556          Expression exp;
3557          if(stmt.expressions)
3558          {
3559             ((Expression)stmt.expressions->last).usage.usageGet = true;
3560             for(exp = stmt.expressions->first; exp; exp = exp.next)
3561             {
3562                ProcessExpression(exp);
3563                // TOCHECK: This was added 2013/02/09 as part of 64 bit port for structs in class properties to automatically be returned by reference
3564                if(!exp.next && exp.destType && exp.destType.byReference)
3565                   FixReference(exp, true);
3566             }
3567          }
3568          break;
3569       }
3570       case badDeclarationStmt:
3571       {
3572          ProcessDeclaration(stmt.decl);
3573          break;
3574       }
3575       case asmStmt:
3576       {
3577          AsmField field;
3578          if(stmt.asmStmt.inputFields)
3579          {
3580             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
3581                if(field.expression)
3582                   ProcessExpression(field.expression);
3583          }
3584          if(stmt.asmStmt.outputFields)
3585          {
3586             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
3587                if(field.expression)
3588                   ProcessExpression(field.expression);
3589          }
3590          if(stmt.asmStmt.clobberedFields)
3591          {
3592             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
3593                if(field.expression)
3594                   ProcessExpression(field.expression);
3595          }
3596          break;
3597       }
3598    }
3599 }
3600
3601 static void ProcessFunction(FunctionDefinition function)
3602 {
3603    if(function.body)
3604       ProcessStatement(function.body);
3605 }
3606
3607 static void ProcessMemberInitData(MemberInit member)
3608 {
3609    if(member.initializer)
3610       ProcessInitializer(member.initializer);
3611 }
3612
3613 static void ProcessInstantiation(Instantiation inst)
3614 {
3615    if(inst.members)
3616    {
3617       MembersInit members;
3618       for(members = inst.members->first; members; members = members.next)
3619       {
3620          if(members.type == dataMembersInit)
3621          {
3622             if(members.dataMembers)
3623             {
3624                MemberInit member;
3625                for(member = members.dataMembers->first; member; member = member.next)
3626                   ProcessMemberInitData(member);
3627             }
3628          }
3629          else if(members.type == methodMembersInit)
3630          {
3631             ProcessFunction((FunctionDefinition)members.function);
3632          }
3633       }
3634    }
3635 }
3636
3637 /////////// MEMBER ACCESS PASS /////////////////////////////////////////////
3638 public void ProcessMemberAccess()
3639 {
3640    External external;
3641    for(external = ast->first; external; external = external.next)
3642    {
3643       curExternal = external;
3644       // There shouldn't be any class member access here anyways...
3645       if(external.type == declarationExternal)
3646       {
3647          if(external.declaration)
3648             ProcessDeclaration(external.declaration);
3649       }
3650    }
3651
3652    for(external = ast->first; external; external = external.next)
3653    {
3654       curExternal = external;
3655       if(external.type == functionExternal)
3656       {
3657          ProcessFunction(external.function);
3658       }
3659       else if(external.type == declarationExternal)
3660       {
3661          if(external.declaration)
3662             ProcessDeclaration(external.declaration);
3663       }
3664       else if(external.type == classExternal)
3665       {
3666          ClassDefinition _class = external._class;
3667          if(_class.definitions)
3668          {
3669             ClassDef def;
3670             Class regClass = _class.symbol.registered;
3671
3672             // Process all functions
3673             for(def = _class.definitions->first; def; def = def.next)
3674             {
3675                if(def.type == functionClassDef)
3676                {
3677                   curExternal = def.function.declarator.symbol.pointerExternal;
3678                   ProcessFunction((FunctionDefinition)def.function);
3679                }
3680                else if(def.type == declarationClassDef && def.decl.type == instDeclaration)
3681                {
3682                   ProcessInstantiation(def.decl.inst);
3683                }
3684                else if(def.type == defaultPropertiesClassDef && def.defProperties)
3685                {
3686                   MemberInit defProperty;
3687
3688                   // Add this to the context
3689                   Symbol thisSymbol
3690                   {
3691                      string = CopyString("this");
3692                      type = MkClassType(regClass.fullName);
3693                   };
3694                   globalContext.symbols.Add((BTNode)thisSymbol);
3695
3696                   for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
3697                   {
3698                      //thisClass = regClass;
3699                      ProcessMemberInitData(defProperty); //, regClass, &id);
3700                      //thisClass = null;
3701                   }
3702
3703                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3704                   globalContext.symbols.Remove((BTNode)thisSymbol);
3705                   FreeSymbol(thisSymbol);
3706                }
3707                else if(def.type == propertyClassDef && def.propertyDef)
3708                {
3709                   PropertyDef prop = def.propertyDef;
3710
3711                   // Add this to the context
3712                   Symbol thisSymbol
3713                   {
3714                      string = CopyString("this");
3715                      type = MkClassType(regClass.fullName);
3716                   };
3717                   globalContext.symbols.Add((BTNode)thisSymbol);
3718
3719                   //thisClass = regClass;
3720                   if(prop.setStmt)
3721                   {
3722                      curExternal = prop.symbol.externalSet;
3723                      ProcessStatement(prop.setStmt);
3724                   }
3725                   if(prop.getStmt)
3726                   {
3727                      curExternal = prop.symbol.externalGet;
3728                      ProcessStatement(prop.getStmt);
3729                   }
3730                   if(prop.issetStmt)
3731                   {
3732                      curExternal = prop.symbol.externalIsSet;
3733                      ProcessStatement(prop.issetStmt);
3734                   }
3735
3736                   //thisClass = null;
3737
3738                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3739                   globalContext.symbols.Remove((BTNode)thisSymbol);
3740                   FreeSymbol(thisSymbol);
3741                }
3742                else if(def.type == classPropertyClassDef && def.propertyDef)
3743                {
3744                   PropertyDef prop = def.propertyDef;
3745
3746                   //thisClass = regClass;
3747                   if(prop.setStmt)
3748                   {
3749                      curExternal = prop.symbol.externalSet;
3750                      ProcessStatement(prop.setStmt);
3751                   }
3752                   if(prop.getStmt)
3753                   {
3754                      curExternal = prop.symbol.externalGet;
3755                      ProcessStatement(prop.getStmt);
3756                   }
3757                   //thisClass = null;
3758                }
3759                else if(def.type == propertyWatchClassDef && def.propertyWatch)
3760                {
3761                   PropertyWatch propertyWatch = def.propertyWatch;
3762
3763                   // Add this to the context
3764                   Symbol thisSymbol
3765                   {
3766                      string = CopyString("this");
3767                      type = MkClassType(regClass.fullName);
3768                   };
3769                   globalContext.symbols.Add((BTNode)thisSymbol);
3770
3771                   //thisClass = regClass;
3772                   if(propertyWatch.compound)
3773                   {
3774                      Symbol thisSymbol
3775                      {
3776                         string = CopyString("this");
3777                         type = MkClassType(regClass.fullName);
3778                      };
3779                      propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
3780                      curExternal = null;
3781                      ProcessStatement(propertyWatch.compound);
3782                   }
3783                   // thisClass = null;
3784
3785                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3786                   globalContext.symbols.Remove((BTNode)thisSymbol);
3787                   FreeSymbol(thisSymbol);
3788                }
3789             }
3790          }
3791       }
3792    }
3793 }