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