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