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