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