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