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