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