compiler/libec: Null checks
[sdk] / compiler / libec / src / pass0.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7
8 public void FullClassNameCat(char * output, const char * className, bool includeTemplateParams)
9 {
10    int c;
11    char ch;
12    int len;
13    /*
14    if(!strchr(className, ':'))
15    {
16       output[len++] = '_';
17       output[len++] = '_';
18    }
19    */
20    //if(strchr(className, ':'))
21    for(c = 0; (ch = className[c]) && ch != '<'; c++)
22    {
23       if(ch == ':')
24       {
25          strcat(output, "__ecereNameSpace__");
26          break;
27       }
28    }
29
30    len = strlen(output);
31
32    c = 0;
33    if(!strncmp(className, "const ", 6)) c += 6;
34
35    for(; (ch = className[c]); c++)
36    {
37       if(ch == ':')
38          output[len++] = '_';
39       else if(ch == ' ')
40          output[len++] = '_';
41       else if(ch == '*')
42       {
43          output[len++] = '_';
44          output[len++] = 'P';
45          output[len++] = 'T';
46          output[len++] = 'R';
47          output[len++] = '_';
48       }
49       else if(ch == '=')
50       {
51          output[len++] = '_';
52          output[len++] = 'E';
53          output[len++] = 'Q';
54          output[len++] = 'U';
55          output[len++] = '_';
56       }
57       else if(ch == '<')
58       {
59          if(!includeTemplateParams) break;
60          if(!strncmp(className + c + 1, "const ", 6)) c += 6;
61          output[len++] = '_';
62          output[len++] = 'T';
63          output[len++] = 'P';
64          output[len++] = 'L';
65          output[len++] = '_';
66       }
67       else if(ch == '>')
68       {
69          output[len++] = '_';
70       }
71       else if(ch == ',')
72       {
73          if(!strncmp(className + c + 1, "const ", 6)) c += 6;
74          output[len++] = '_';
75       }
76       else
77          output[len++] = ch;
78    }
79    output[len++] = 0;
80 }
81
82 static void AddSimpleBaseMembers(External external, OldList list, Class _class, Class topClass)
83 {
84    if(_class.type != systemClass)
85       AddMembers(external, list, _class, false, null, topClass, null);
86 }
87
88 static bool NameSpaceContained(NameSpace * ns, NameSpace * parent)
89 {
90    if(ns == parent)
91       return true;
92    else if(ns->parent)
93       return NameSpaceContained(ns->parent, parent);
94    else
95       return false;
96 }
97
98 static void CheckPublicClass(Symbol classSym, AccessMode access, const char * word)
99 {
100    Class regClass = classSym ? classSym.registered : null;
101    if(regClass)
102    {
103       if(regClass.templateClass)
104          regClass = regClass.templateClass;
105       // TODO: Will need to add checks for template parameter classes
106       if(classSym.isStatic && access != staticAccess)
107       {
108          Compiler_Error($"Non-static %s making use of a static class\n", word);
109       }
110       else if(access == publicAccess)
111       {
112          if(!NameSpaceContained(regClass.nameSpace, regClass.module.application.systemNameSpace))
113          {
114             if(NameSpaceContained(regClass.nameSpace, regClass.module.privateNameSpace) || !ModuleAccess(privateModule, regClass.module))
115                Compiler_Error($"Public %s making use of a private class\n", word);
116          }
117       }
118    }
119 }
120
121 static void CheckPublicTypeName(TypeName type, AccessMode access)
122 {
123    if(type.qualifiers)
124    {
125       Specifier spec;
126       for(spec = type.qualifiers->first; spec; spec = spec.next)
127       {
128          // Only check for classes here...
129          // Skip structs etc. for now
130          if(spec.type == nameSpecifier)
131          {
132             Symbol classSym = spec.symbol; // FindClass(spec.name);
133             CheckPublicClass(classSym, access, "define");
134          }
135       }
136    }
137 }
138
139 static void CheckPublicInitializer(Initializer init, AccessMode access)
140 {
141    switch(init.type)
142    {
143       case expInitializer:
144          CheckPublicExpression(init.exp, access);
145          break;
146       case listInitializer:
147       {
148          Initializer i;
149          for(i = init.list->first; i; i = i.next)
150             CheckPublicInitializer(i, access);
151          break;
152       }
153    }
154 }
155
156 static void CheckPublicExpression(Expression exp, AccessMode access)
157 {
158    if(exp)
159    {
160       switch(exp.type)
161       {
162          case identifierExp:
163             break;
164          case constantExp:
165             break;
166          case stringExp:
167             break;
168          case opExp:
169             if(exp.op.exp1)
170                CheckPublicExpression(exp.op.exp1, access);
171             if(exp.op.exp2)
172                CheckPublicExpression(exp.op.exp2, access);
173             break;
174          case bracketsExp:
175          {
176             Expression e;
177             for(e = exp.list->first; e; e = e.next)
178                CheckPublicExpression(e, access);
179             break;
180          }
181          case indexExp:
182          {
183             Expression e;
184             CheckPublicExpression(exp.index.exp, access);
185             for(e = exp.index.index->first; e; e = e.next)
186                CheckPublicExpression(e, access);
187             break;
188          }
189          case callExp:
190          {
191             Expression e;
192             CheckPublicExpression(exp.call.exp, access);
193             if(exp.call.arguments)
194             {
195                for(e = exp.call.arguments->first; e; e = e.next)
196                   CheckPublicExpression(e, access);
197             }
198             break;
199          }
200          case memberExp:
201          {
202             CheckPublicExpression(exp.member.exp, access);
203             break;
204          }
205          case pointerExp:
206          {
207             CheckPublicExpression(exp.member.exp, access);
208             break;
209          }
210          case typeSizeExp:
211             CheckPublicTypeName(exp.typeName, access);
212             break;
213          case castExp:
214          {
215             CheckPublicTypeName(exp.cast.typeName, access);
216             if(exp.cast.exp)
217                CheckPublicExpression(exp.cast.exp, access);
218             break;
219          }
220          case conditionExp:
221          {
222             Expression e;
223             CheckPublicExpression(exp.cond.cond, access);
224             for(e = exp.cond.exp->first; e; e = e.next)
225                CheckPublicExpression(e, access);
226             CheckPublicExpression(exp.cond.elseExp, access);
227             break;
228          }
229          case newExp:
230          case new0Exp:
231             CheckPublicExpression(exp._new.size, access);
232             break;
233          case renewExp:
234          case renew0Exp:
235             CheckPublicExpression(exp._renew.size, access);
236             CheckPublicExpression(exp._renew.exp, access);
237             break;
238          case instanceExp:
239          {
240             MembersInit members;
241             CheckPublicClass(exp.instance._class.symbol /*FindClass(exp.instance._class.name)*/, access, "define");
242             for(members = exp.instance.members->first; members; members = members.next)
243             {
244                if(members.type == dataMembersInit)
245                {
246                   MemberInit member;
247                   for(member = members.dataMembers->first; member; member = member.next)
248                   {
249                      CheckPublicInitializer(member.initializer, access);
250                   }
251                }
252             }
253             break;
254          }
255       }
256    }
257 }
258
259 static void CheckPublicDataType(Type type, AccessMode access, const char * word)
260 {
261    if(type)
262    {
263       switch(type.kind)
264       {
265          case classType:
266          {
267             CheckPublicClass(type._class, access, word);
268             break;
269          }
270          case structType:
271          case unionType:
272          {
273             // Do we want to overlook these C constructs when doing checks? Most likely... Recursion nightmare.
274             /*
275             Type member;
276             Symbol typeSym;
277             if(type.enumName)
278             {
279                typeSym = FindSymbol(type.enumName, globalContext, globalContext, true, false);
280                if(typeSym) type = typeSym.type;
281             }
282             for(member = type.members.first; member; member = member.next)
283                CheckPublicDataType(member, access, word);
284             */
285             break;
286          }
287          case functionType:
288          {
289             Type param;
290             CheckPublicDataType(type.returnType, access, word);
291             for(param = type.params.first; param; param = param.next)
292                CheckPublicDataType(param, access, word);
293             CheckPublicClass(type.thisClass, access, word);
294             break;
295          }
296          case arrayType:
297             CheckPublicDataType(type.arrayType, access, word);
298             if(type.enumClass)
299                CheckPublicClass(type.enumClass, access, word);
300             break;
301          case pointerType:
302          {
303             CheckPublicDataType(type.type, access, word);
304             break;
305          }
306          case methodType:
307          {
308             // Where is this used? Needed?
309             break;
310          }
311          case subClassType:
312          {
313             CheckPublicClass(type._class, access, word);
314             break;
315          }
316       }
317    }
318 }
319
320 static void CheckMembersDefinitions(Class regClass, DataMember member, OldList definitions, AccessMode access)
321 {
322    if(definitions != null)
323    {
324       ClassDef def;
325       for(def = definitions.first; def; def = def.next)
326       {
327          if(def.type == declarationClassDef)
328          {
329             Declaration decl = def.decl;
330             DataMember dataMember;
331
332             yylloc = def.loc;
333             if(decl.type == structDeclaration)
334             {
335                Declarator d;
336                if(decl.declarators)
337                {
338                   for(d = decl.declarators->first; d; d = d.next)
339                   {
340                      Identifier declId = GetDeclId(d);
341                      if(declId)
342                      {
343                         if(member)
344                         {
345                            BTNamedLink link = (BTNamedLink)member.membersAlpha.FindString(declId.string);
346                            dataMember = link ? link.data : null;
347                         }
348                         else
349                            dataMember = eClass_FindDataMember(regClass, declId.string, privateModule, null, null);
350                         if(dataMember)
351                            CheckPublicDataType(dataMember.dataType,  (def.memberAccess == privateAccess) ? privateAccess : access, $"class data member");
352                      }
353                   }
354                }
355                else if(decl.specifiers)
356                {
357                   Specifier spec;
358                   // Unnamed struct/union
359                   for(spec = decl.specifiers->first; spec; spec = spec.next)
360                   {
361                      if(spec.type == structSpecifier || spec.type == unionSpecifier)
362                      {
363                         if(spec.definitions && !spec.id)
364                         {
365                            CheckMembersDefinitions(regClass, member, spec.definitions, (def.memberAccess == privateAccess) ? privateAccess : access);
366                         }
367                         else if(spec.definitions && spec.id)
368                         {
369                            if(member)
370                            {
371                               BTNamedLink link = (BTNamedLink)member.membersAlpha.FindString(spec.id.string);
372                               dataMember = link ? link.data : null;
373                            }
374                            else
375                               dataMember = eClass_FindDataMember(regClass, spec.id.string, privateModule, null, null);
376                            if(dataMember)
377                               CheckPublicDataType(dataMember.dataType,  (def.memberAccess == privateAccess) ? privateAccess : access, $"class data member");
378                         }
379                      }
380                   }
381                }
382             }
383             else if(decl.type == instDeclaration)
384             {
385                CheckPublicClass(decl.inst._class.symbol /*FindClass(decl.inst._class.name)*/, (def.memberAccess == privateAccess) ? privateAccess : access, $"class member instance");
386             }
387          }
388       }
389    }
390 }
391
392 static void ProcessClass(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues, Location loc, OldList defs, void * after, OldList initDeclarators, ExtDecl extDecl)
393 {
394    char structName[1024];
395    char className[1024];
396    char constructorName[1024];
397    char destructorName[1024];
398    Class regClass;
399    ClassFunction destructor = null, constructor = null;
400    //bool redefinition = false;
401    bool isUnion = classType == unionClass;
402
403    External external = null;
404
405    ClassDef def;
406    OldList * list = null;
407    OldList * classDataList = null;
408
409    if(inCompiler)
410    {
411       list = MkList();
412       classDataList = MkList();
413    }
414
415    /*
416       TODO: Analyze This
417    if(symbol.exclude)
418    {
419       if(inCompiler)
420          return;
421       else
422          redefinition = true;
423    }
424    */
425    regClass = eSystem_FindClass(privateModule, symbol.string);
426    if(!regClass)
427       return;  // TODO: Notify of an error?
428    classType = regClass.type;
429
430    // PUBLISHING CHECK ON BASE CLASS
431    if(inCompiler && regClass.base)  // The base check saves a crash trying to inherit from itself
432    {
433       yylloc = loc;
434
435       if(!NameSpaceContained(regClass.nameSpace, &regClass.module.privateNameSpace) && regClass.inheritanceAccess == publicAccess)
436       {
437          if(!regClass.base.symbol)
438             regClass.base.symbol = FindClass(regClass.base.fullName);
439          CheckPublicClass(regClass.base.symbol, publicAccess, $"class");
440       }
441       else if(!symbol.isStatic && regClass.base)
442       {
443          if(!regClass.base.symbol)
444             regClass.base.symbol = FindClass(regClass.base.fullName);
445          CheckPublicClass(regClass.base.symbol, privateAccess, $"class");
446       }
447    }
448
449    /*
450    if(NameSpaceContained(regClass.nameSpace, &regClass.module.privateNameSpace))
451    {
452       if(regClass.inheritanceAccess == publicAccess &&
453          (regClass.base.nameSpace == &regClass.base.module.privateNameSpace || !ModuleAccess(privateModule, regClass.base.module)))
454          Compiler_Error($"Public class publicly inheriting off private base class\n");
455    }
456    else if(!symbol.isStatic)
457    {
458       Symbol baseSym = FindClass(regClass.base.fullName);
459       if(baseSym && baseSym.isStatic)
460          Compiler_Error($"Non-static class inheriting off static base class\n");
461    }
462    */
463
464    /*
465    MOVED ENUM VALUES TO PASS1
466
467    if(classType == enumClass && enumValues)
468    {
469       Enumerator e;
470       for(e = enumValues.first; e; e = e.next)
471       {
472          if(e.exp)
473          {
474             Type destType
475             {
476                kind = TypeInt;
477                refCount = 1;
478             };
479             e.exp.destType = destType;
480
481             ProcessExpressionType(e.exp);
482             ComputeExpression(e.exp);
483             if(e.exp.isConstant && e.exp.type == ExpConstant)
484             {
485                int value;
486                value = strtol(e.exp.string, null, 0);
487                eEnum_AddFixedValue(regClass, e.id.string, value);
488             }
489             else
490                // Sort of an error
491                eEnum_AddValue(regClass, e.id.string);
492          }
493          else
494             eEnum_AddValue(regClass, e.id.string);
495       }
496    }
497    */
498
499    // ACCESS OVERRIDING CODE
500    if(definitions != null)
501    {
502       for(def = definitions.first; def; def = def.next)
503       {
504          if(def.type == accessOverrideClassDef)
505          {
506             DataMember member;
507             Property prop;
508             Method method;
509             if((prop = eClass_FindProperty(regClass, def.id.string, privateModule)))
510             {
511                eClass_AddProperty(regClass, def.id.string, null, null, null, def.memberAccess);
512             }
513             else if((member = eClass_FindDataMember(regClass, def.id.string, privateModule, null, null)))
514             {
515                eClass_AddDataMember(regClass, def.id.string, null, 0, 0, def.memberAccess);
516             }
517             else if((method = eClass_FindMethod(regClass, def.id.string, privateModule)))
518             {
519                eClass_AddMethod(regClass, def.id.string, null, null, def.memberAccess);
520             }
521             else
522             {
523                yylloc = def.loc;
524                Compiler_Error($"Couldn't find member %s to override\n", def.id.string);
525             }
526          }
527       }
528    }
529
530    if(inCompiler)
531    {
532       external = MkExternalDeclaration(null);
533       defs.Insert(after, external);
534       curExternal = external;
535       curExternal.symbol = symbol;
536    }
537
538    if((classType == structClass || classType == noHeadClass) && inCompiler)
539    {
540       AddSimpleBaseMembers(external, list, regClass.base, regClass);
541    }
542
543    // First check if there's any declaration or instantiations, we'll need a struct
544    if(definitions != null)
545    {
546       if(inCompiler)
547       {
548          if(!NameSpaceContained(regClass.nameSpace, &regClass.module.privateNameSpace))
549             CheckMembersDefinitions(regClass, null, definitions, publicAccess);
550          else if(!symbol.isStatic)
551             CheckMembersDefinitions(regClass, null, definitions, privateAccess);
552       }
553       for(def = definitions.first; def; def = def.next)
554       {
555          yylloc = def.loc;
556          if(def.type == declarationClassDef)
557          {
558             Declaration decl = def.decl;
559             yylloc = decl.loc;
560
561             if(decl.type == structDeclaration)
562             {
563                if(inCompiler && classType != bitClass)
564                {
565                   ListAdd(list, MkClassDefDeclaration(decl));
566
567                   // Take it out from here...
568                   def.decl = null;
569                }
570             }
571             else if(decl.type == instDeclaration)
572             {
573                Instantiation inst = decl.inst;
574                Expression exp = inst.exp;
575                Symbol classSym;
576                if(exp)
577                {
578                   // Eventually support multiple instance creations in the same ';'
579                   OldList * specifiers = MkList();
580                   Declarator d;
581
582                   ListAdd(specifiers, MkSpecifierName/*MkClassName*/(inst._class.name));
583                   d = MkDeclaratorIdentifier(MkIdentifier(exp.identifier.string));
584
585                   if(inCompiler)
586                   {
587                      OldList * declarators = MkList();
588                      ListAdd(declarators, d);
589
590                      decl = MkStructDeclaration(specifiers, declarators, null);
591                      ListAdd(list, MkClassDefDeclaration(decl));
592
593                      // Add the this pointer to the instance expression
594                      exp.type = memberExp;
595                      exp.member.member = exp.identifier;
596                      exp.member.exp = QMkExpId("this");
597                      exp.member.memberType = dataMember;
598                      exp.member.thisPtr = true;
599                   }
600                   else
601                   {
602                      FreeDeclarator(d);
603                      FreeList(specifiers, FreeSpecifier);
604                   }
605                }
606
607                // Check if it is a simple class
608                // If it is, we only need a constructor if there is data set,
609                // and we don't need a destructor
610                classSym = inst._class.symbol; // FindClass(inst._class.name);
611                if(classSym && classSym.registered &&
612                   (classSym.registered.type == structClass ||
613                    classSym.registered.type == bitClass ||
614                    classSym.registered.type == unitClass))
615                {
616                   if(inst.members && inst.members->count)
617                      symbol.needConstructor = true;
618                }
619                else
620                {
621                   symbol.needConstructor = true;
622                   symbol.needDestructor = true;
623                }
624             }
625          }
626          else if(def.type == classDataClassDef)
627          {
628             Declaration decl = def.decl;
629
630             if(decl.type == structDeclaration)
631             {
632                if(inCompiler && classType != bitClass)
633                {
634                   ListAdd(classDataList, MkClassDefDeclaration(decl));
635
636                   // Take it out from here...
637                   def.decl = null;
638                }
639             }
640          }
641          else if(def.type == defaultPropertiesClassDef)
642             symbol.needConstructor = true;
643          else if(def.type == propertyWatchClassDef)
644             symbol.needConstructor = true;
645          else if(def.type == functionClassDef)
646          {
647             ClassFunction func = def.function;
648             if(func.isDestructor)
649             {
650                if(destructor)
651                {
652                   yylloc = loc;
653                   Compiler_Error($"redefinition of destructor for class %s\n", symbol.string);
654                }
655                else
656                {
657                   symbol.needDestructor = true;
658                   destructor = func;
659                   if(!inCompiler && func.body)
660                   {
661                      // Add this to the context
662                      Symbol thisSymbol
663                      {
664                         string = CopyString("this");
665                         type = MkClassType(regClass.fullName);
666                      };
667                      func.body.compound.context.symbols.Add((BTNode)thisSymbol);
668                   }
669                }
670             }
671             if(func.isConstructor)
672             {
673                if(constructor)
674                {
675                   yylloc = loc;
676                   Compiler_Error($"redefinition of constructor for class %s\n", symbol.string);
677                }
678                else
679                {
680                   symbol.needConstructor = true;
681                   constructor = func;
682
683                   if(!inCompiler && func.body)
684                   {
685                      // Add this to the context
686                      Symbol thisSymbol
687                      {
688                         string = CopyString("this");
689                         type = MkClassType(regClass.fullName);
690                      };
691                      func.body.compound.context.symbols.Add((BTNode)thisSymbol);
692                   }
693                }
694             }
695          }
696       }
697    }
698
699    if(inCompiler)
700    {
701       external.symbol = null;
702
703       if(list->count)
704       {
705          // We need a struct
706          OldList * specs = MkList(), * declarators = (initDeclarators != null) ? initDeclarators : MkList();
707          initDeclarators = null;
708
709          // TESTING THIS HERE INSTEAD:
710          strcpy(structName, symbol.string);
711          symbol.structName = CopyString(structName);
712
713          {
714             Specifier spec = MkStructOrUnion(structSpecifier, MkIdentifier(structName),
715                isUnion ? MkListOne(MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkStructOrUnion(unionSpecifier, null, list)), null, null))) : list);
716             spec.extDeclStruct = extDecl;
717             ListAdd(specs, spec);
718          }
719
720          external.symbol = symbol;
721          if(symbol.structExternal)
722          {
723             for(e : symbol.structExternal.incoming)
724                external.CreateUniqueEdge(e.from, e.breakable);
725             for(e : symbol.structExternal.outgoing)
726                e.to.CreateUniqueEdge(external, e.breakable);
727             ast->Remove(symbol.structExternal);
728             FreeExternal(symbol.structExternal);
729          }
730          symbol.structExternal = external;
731
732          external.declaration = MkDeclaration(specs, declarators);
733          after = external;
734
735          symbol.declaredStruct = true;
736       }
737       else
738       {
739          curExternal = external.prev;
740          defs.Remove(external);
741          FreeExternal(external);
742          delete list;
743       }
744
745       if(classDataList->count)
746       {
747          // We need a struct
748          char classDataStructName[1024];
749          OldList * specs = MkList();
750          External external;
751
752          strcpy(classDataStructName, "__ecereClassData_");
753          FullClassNameCat(classDataStructName, symbol.string, false);
754
755          declMode = structDeclMode = defaultAccess;
756          ListAdd(specs, MkStructOrUnion(structSpecifier, MkIdentifier(classDataStructName), classDataList));
757          external = MkExternalDeclaration(MkDeclaration(specs, null));
758          defs.Insert(after, external);
759          after = external;
760          symbol.classData = true;
761       }
762       else
763          delete classDataList;
764    }
765
766    if(inCompiler)
767    {
768       // Class
769       {
770          OldList * specs = MkList(), * declarators = MkList();
771          strcpy(className, "__ecereClass_");
772          FullClassNameCat(className, symbol.string, true);
773
774          symbol.className = CopyString(className);
775
776          if(!strstr(sourceFile, ".main.ec"))
777             ListAdd(specs, MkSpecifier(STATIC));
778          ListAdd(specs, MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
779          ListAdd(declarators, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null),
780             MkDeclaratorIdentifier(MkIdentifier(className))), null));
781
782          symbol.pointerExternal = MkExternalDeclaration(MkDeclaration(specs, declarators));
783          DeclareStruct(symbol.pointerExternal, "ecere::com::Class", false, true);
784
785          defs.Insert(after, symbol.pointerExternal);
786          after = symbol.methodExternal;
787       }
788
789       // Build the destructor
790       if(symbol.needDestructor)
791       {
792          ClassFunction function;
793          OldList * specs = MkList();
794          Declarator decl;
795          Statement body;
796          Context context;
797          OldList * declarations = null, * statements;
798
799          strcpy(destructorName, "__ecereDestructor_");
800          FullClassNameCat(destructorName, symbol.string, false);
801
802          symbol.destructorName = CopyString(destructorName);
803
804          ListAdd(specs, MkSpecifier(VOID));
805
806          context = PushContext();
807
808          statements = MkList();
809
810          if(definitions != null)
811          {
812             for(def = definitions.first; def; def = def.next)
813             {
814                // Get rid of stuff
815                if(def.type == declarationClassDef && def.decl && def.decl.type == instDeclaration)
816                {
817                   Instantiation inst = def.decl.inst;
818                   Symbol classSym = inst._class.symbol;
819                   /*if(!classSym)
820                      classSym = inst._class.symbol = FindClass(inst._class.name);*/
821                   if(inst.exp && (!classSym || !classSym.registered || classSym.registered.type == normalClass))
822                   {
823                      /*  FIX a DecRef declaration problem...
824                      // Decrement counter if it isn't a simple class
825                      ListAdd(statements,
826                         MkExpressionStmt(MkListOne(MkExpCall(
827                            MkExpIdentifier(MkIdentifier("ecere::com::eInstance_DecRef")),
828                            MkListOne(CopyExpression(inst.exp))))));
829                      */
830                      Expression exp = MkExpOp(null, DELETE, CopyExpression(inst.exp));
831                      ListAdd(statements, MkExpressionStmt(MkListOne(exp)));
832                   }
833                   if(inst.exp && (!classSym || !classSym.registered || classSym.registered.type == noHeadClass))
834                   {
835                      Expression exp = MkExpOp(null, DELETE, CopyExpression(inst.exp));
836                      ListAdd(statements, MkExpressionStmt(MkListOne(exp)));
837                   }
838                }
839             }
840          }
841
842          if(destructor && destructor.body)
843          {
844             /*
845             declarations = destructor.body.compound.declarations;
846             if(destructor.body.compound.statements)
847             {
848                Statement stmt;
849                while(stmt = destructor.body.compound.statements.first)
850                {
851                   destructor.body.compound.statements->Remove(stmt);
852                   statements->Add(stmt);
853                }
854             }
855             */
856             // statements->Add(destructor.body);
857             statements->Insert(null, destructor.body);
858             destructor.body.compound.context.parent = context;
859             destructor.body = null;
860          }
861
862          body = MkCompoundStmt(declarations, statements);
863          PopContext(context);
864          body.compound.context = context;
865
866          decl = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(destructorName)), null);
867
868          decl.symbol = Symbol { };
869          excludedSymbols->Add(decl.symbol);
870
871          function = MkClassFunction(specs, null, decl, null);
872          ProcessClassFunctionBody(function, body);
873          function.dontMangle = true;
874          definitions.Insert(null, MkClassDefFunction(function));
875       }
876
877       // Build the constructor
878
879       if(symbol.needConstructor && inCompiler)
880       {
881          ClassFunction function;
882          OldList * specs = MkList();
883          Declarator decl;
884          Statement body;
885          Context context;
886          OldList * declarations = null, * statements;
887
888          strcpy(constructorName, "__ecereConstructor_");
889          FullClassNameCat(constructorName, symbol.string, false);
890
891          symbol.constructorName = CopyString(constructorName);
892
893          ListAdd(specs, MkSpecifierName/*MkClassName*/("bool"));
894
895          context = PushContext();
896
897          statements = MkList();
898
899          if(definitions != null)
900          {
901             for(def = definitions.first; def; def = def.next)
902             {
903                if(def.type == declarationClassDef && def.decl && def.decl.type == instDeclaration)
904                {
905                   Instantiation inst = def.decl.inst;
906                   Symbol classSym = inst._class.symbol; // FindClass(inst._class.name);
907                   /*if(!classSym)
908                      classSym = inst._class.symbol = FindClass(inst._class.name);*/
909
910                   if(inst.exp && (!classSym || !classSym.registered || classSym.registered.type == normalClass || classSym.registered.type == noHeadClass))
911                   {
912                      Instantiation newInst { };
913                      *newInst = *inst;
914                      newInst.members = null;
915                      newInst.exp = CopyExpression(inst.exp);
916                      newInst._class = CopySpecifier(inst._class);
917
918                      ListAdd(statements,
919                         MkExpressionStmt(MkListOne(MkExpInstance(newInst))));
920                      inst.built = true;
921                   }
922
923                   // Increment counter if it isn't a simple class
924                   if(inst.exp && (!classSym || !classSym.registered || classSym.registered.type == normalClass))
925                   {
926                      ListAdd(statements,
927                         MkExpressionStmt(MkListOne(MkExpCall(
928                            MkExpIdentifier(MkIdentifier("ecere::com::eInstance_IncRef")),
929                            MkListOne(CopyExpression(inst.exp))))));
930                   }
931                }
932             }
933
934             for(def = definitions.first; def; def = def.next)
935             {
936                // Add the default data properties/members
937                if(def.type == defaultPropertiesClassDef && def.defProperties)
938                {
939                   MemberInit propertyDef;
940                   for(propertyDef = def.defProperties->first; propertyDef; propertyDef = propertyDef.next)
941                   {
942                      Expression memberExp;
943                      Identifier id = propertyDef.identifiers->first;
944                      if(id)
945                      {
946                         memberExp = MkExpMember(MkExpIdentifier(MkIdentifier("this")), id);
947                         for(id = id.next; id; id = id.next)
948                            memberExp = MkExpMember(memberExp, id);
949
950                         // ASSUME: No list initializers here
951                         ListAdd(statements,
952                            MkExpressionStmt(MkListOne(MkExpOp(memberExp, '=',
953                               (propertyDef.initializer && propertyDef.initializer.type == expInitializer ? propertyDef.initializer.exp : null)))));
954
955                      }
956                      // Take it out of there...
957                      if(propertyDef.initializer)
958                      {
959                         if(propertyDef.initializer.type == expInitializer)
960                            propertyDef.initializer.exp = null;
961                         FreeInitializer(propertyDef.initializer);
962                      }
963                      propertyDef.initializer = null;
964                      propertyDef.identifiers->Clear();
965                   }
966                }
967             }
968             for(def = definitions.first; def; def = def.next)
969             {
970                // Instanciate stuff
971                if(def.type == declarationClassDef && def.decl && def.decl.type == instDeclaration)
972                {
973                   Instantiation inst = def.decl.inst;
974                   Symbol classSym = inst._class.symbol; // FindClass(inst._class.name);
975                   /*if(!classSym)
976                      classSym = inst._class.symbol = FindClass(inst._class.name);*/
977
978                   if(inst.exp || (!classSym || !classSym.registered || classSym.registered.type == normalClass || classSym.registered.type == noHeadClass))
979                   {
980                      // Only needed here if members are set...
981                      if(!(inst.exp && (!classSym || !classSym.registered || classSym.registered.type == normalClass || classSym.registered.type == noHeadClass)) || (inst.members && inst.members->count))
982                      {
983                         // Is it safe to take it out here?
984                         def.decl.inst = null;
985
986                         ListAdd(statements,
987                            MkExpressionStmt(MkListOne(MkExpInstance(inst))));
988                      }
989                   }
990                }
991             }
992          }
993
994          if(constructor && constructor.body)
995          {
996             /*
997             declarations = constructor.body.compound.declarations;
998
999             if(constructor.body.compound.declarations)
1000             {
1001                Declaration decl;
1002                while(decl = constructor.body.compound.declarations.first)
1003                {
1004                   constructor.body.compound.declarations->Remove(decl);
1005                   declarations->Add(decl);
1006                }
1007             }
1008
1009             // We want to keep the context here...
1010             if(constructor.body.compound.statements)
1011             {
1012                Statement stmt;
1013                while(stmt = constructor.body.compound.statements.first)
1014                {
1015                   constructor.body.compound.statements->Remove(stmt);
1016                   statements->Add(stmt);
1017                }
1018             }
1019             */
1020             statements->Add(constructor.body);
1021             constructor.body.compound.context.parent = context;
1022             constructor.body = null;
1023          }
1024
1025          ListAdd(statements, MkReturnStmt(MkListOne(MkExpIdentifier(MkIdentifier("true")))));
1026          body = MkCompoundStmt(declarations, statements);
1027          PopContext(context);
1028          body.compound.context = context;
1029
1030          decl = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(constructorName)), null);
1031
1032          decl.symbol = Symbol { };
1033          excludedSymbols->Add(decl.symbol);
1034
1035          function = MkClassFunction(specs, null, decl, null);
1036          ProcessClassFunctionBody(function, body);
1037          function.dontMangle = true;
1038          if(definitions != null)
1039             definitions.Insert(null, MkClassDefFunction(function));
1040       }
1041    }
1042
1043    // list = null;   // Why was this here?
1044
1045    // Do the functions
1046    if(definitions != null)
1047    {
1048       for(def = definitions.first; def; def = def.next)
1049       {
1050          if(def.type == propertyClassDef && def.propertyDef)
1051          {
1052             PropertyDef propertyDef = def.propertyDef;
1053             ClassDef after = def;
1054             ClassDef newDef;
1055
1056             if(inCompiler)
1057             {
1058                yylloc = propertyDef.loc;
1059                if(!NameSpaceContained(regClass.nameSpace, &regClass.module.privateNameSpace) && def.memberAccess == publicAccess)
1060                   CheckPublicDataType(propertyDef.symbol.type, publicAccess, "class property");
1061                else if(!symbol.isStatic)
1062                   CheckPublicDataType(propertyDef.symbol.type, privateAccess, "class property");
1063             }
1064
1065             {
1066                // Commented this out...  Why exactly?
1067                //if(inCompiler)
1068                {
1069                   ClassFunction func;
1070                   Declarator decl;
1071                   char name[1024];
1072                   OldList * params;
1073                   if(propertyDef.getStmt && propertyDef.id)
1074                   {
1075                      strcpy(name, "__ecereProp_");
1076                      FullClassNameCat(name, symbol.string, false);
1077                      strcat(name, "_Get_");
1078                      // strcat(name, propertyDef.id.string);
1079                      FullClassNameCat(name, propertyDef.id.string, true);
1080
1081                      params = MkList();
1082
1083                      // decl = MkDeclaratorFunction(PlugDeclarator(propertyDef.declarator, MkDeclaratorIdentifier(MkIdentifier(name))), params);
1084
1085                      if(propertyDef.symbol.type && propertyDef.symbol.type.kind == TypeKind::classType && propertyDef.symbol.type._class && propertyDef.symbol.type._class.registered &&
1086                         propertyDef.symbol.type._class.registered.type == structClass)
1087                      {
1088                         ListAdd(params, MkTypeName(CopyList(propertyDef.specifiers, CopySpecifier), MkDeclaratorIdentifier(MkIdentifier("value"))));
1089                         decl = PlugDeclarator(propertyDef.declarator, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(name)), params));
1090
1091                         func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, decl, null);
1092
1093                         // Take it out here...
1094                         //propertyDef.specifiers = null;
1095                      }
1096                      else
1097                      {
1098                         decl = PlugDeclarator(propertyDef.declarator, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(name)), params));
1099
1100                         func = MkClassFunction(CopyList(propertyDef.specifiers, CopySpecifier),
1101                            null, decl, null);
1102                      }
1103
1104                      ProcessClassFunctionBody(func, propertyDef.getStmt);
1105                      func.declarator.symbol = propertyDef.symbol;
1106                      //func.declarator.propSymbol = propertyDef.symbol;
1107                      propertyDef.symbol.externalGet = (External)func;
1108
1109                      func.dontMangle = true;
1110                      newDef = MkClassDefFunction(func);
1111                      definitions.Insert(after, newDef);
1112                      after = newDef;
1113
1114                      if(inCompiler)
1115                         propertyDef.getStmt = null;
1116                      else
1117                         func.body = null;
1118                   }
1119                   if(propertyDef.setStmt && propertyDef.id)
1120                   {
1121                      OldList * specifiers = MkList();
1122
1123                      strcpy(name, "__ecereProp_");
1124                      FullClassNameCat(name, symbol.string, false);
1125                      strcat(name, "_Set_");
1126                      //strcat(name, propertyDef.id.string);
1127                      FullClassNameCat(name, propertyDef.id.string, true);
1128
1129                      params = MkList();
1130
1131                      ListAdd(params, MkTypeName(CopyList(propertyDef.specifiers, CopySpecifier),
1132                         PlugDeclarator(propertyDef.declarator,
1133                            MkDeclaratorIdentifier(MkIdentifier("value")))));
1134
1135                      // Add const to DB table rows properties Set
1136                      if(propertyDef.isDBProp)
1137                      {
1138                         Specifier spec;
1139                         OldList * specs = ((TypeName)params->last).qualifiers;
1140
1141                         for(spec = specs->first; spec; spec = spec.next)
1142                            if(spec.type == baseSpecifier && spec.specifier == CONST)
1143                               break;
1144                         if(!spec)
1145                            specs->Insert(null, MkSpecifier(CONST));
1146                      }
1147
1148                      decl = MkDeclaratorFunction(
1149                         MkDeclaratorIdentifier(MkIdentifier(name)), params);
1150
1151                      {
1152                         bool isConversion = propertyDef.symbol._property && propertyDef.symbol._property.conversion;
1153                         bool useVoid = false;
1154                         switch(regClass.type)
1155                         {
1156                            case structClass: case unionClass:  useVoid = true; break;
1157                            case noHeadClass: case normalClass: useVoid = !isConversion; break;
1158                            default:
1159                               useVoid = !isConversion;
1160                               if(useVoid && !propertyDef.isDBProp)
1161                                  Compiler_Warning($"set defined on type without storage for non-conversion property\n");
1162                         }
1163                         ListAdd(specifiers, useVoid ? MkSpecifier(VOID) : MkSpecifierName(regClass.fullName));
1164                      }
1165
1166                      func = MkClassFunction(specifiers, null, decl, null);
1167                      ProcessClassFunctionBody(func, propertyDef.setStmt);
1168                      func.dontMangle = true;
1169                      func.declarator.symbol = propertyDef.symbol;
1170                      propertyDef.symbol.externalSet = (External)func;
1171                      if(!propertyDef.conversion && regClass.type == normalClass)
1172                         func.propSet = propertyDef.symbol;
1173
1174                      newDef = MkClassDefFunction(func);
1175                      definitions.Insert(after, newDef);
1176                      after = newDef;
1177
1178                      if(inCompiler)
1179                         propertyDef.setStmt = null;
1180                      else
1181                         func.body = null;
1182                   }
1183                   if(propertyDef.issetStmt && propertyDef.id)
1184                   {
1185                      OldList * specifiers = MkList();
1186
1187                      strcpy(name, "__ecereProp_");
1188                      FullClassNameCat(name, symbol.string, false);
1189                      strcat(name, "_IsSet_");
1190                      //strcat(name, propertyDef.id.string);
1191                      FullClassNameCat(name, propertyDef.id.string, true);
1192
1193                      params = MkList();
1194
1195                      decl = MkDeclaratorFunction(
1196                         MkDeclaratorIdentifier(MkIdentifier(name)), params);
1197
1198                      ListAdd(specifiers, MkSpecifierName("bool"));
1199
1200                      func = MkClassFunction(specifiers, null, decl, null);
1201                      ProcessClassFunctionBody(func, propertyDef.issetStmt);
1202                      func.dontMangle = true;
1203                      func.declarator.symbol = propertyDef.symbol;
1204                      //func.declarator.propSymbol = propertyDef.symbol;
1205                      propertyDef.symbol.externalIsSet = (External)func;
1206
1207                      /*
1208
1209                      func.declarator.symbol = Symbol { id = propertyDef.symbol,id + 1, external = (External)func };
1210                      */
1211
1212                      newDef = MkClassDefFunction(func);
1213                      definitions.Insert(after, newDef);
1214                      after = newDef;
1215
1216                      if(inCompiler)
1217                         propertyDef.issetStmt = null;
1218                      else
1219                         func.body = null;
1220                   }
1221                   if(propertyDef.id && inCompiler)
1222                   {
1223                      // Had to put this here because not all properties go through DeclareProperty
1224                      Property prop = eClass_FindProperty(symbol.registered, propertyDef.id.string, privateModule);
1225
1226                      Declaration decl;
1227                      External external;
1228                      OldList * specifiers = MkList();
1229                      specifiers->Insert(null, MkSpecifier(STATIC));
1230                      specifiers->Add(MkSpecifierExtended(MkExtDeclAttrib(MkAttrib(ATTRIB, MkListOne(MkAttribute(CopyString("unused"), null))))));
1231
1232                      ListAdd(specifiers, MkSpecifierName("Property"));
1233                      strcpy(name, "__ecereProp_");
1234                      FullClassNameCat(name, symbol.string, false);
1235                      strcat(name, "_");
1236                      //strcat(name, propertyDef.id.string);
1237                      FullClassNameCat(name, propertyDef.id.string, true);
1238
1239                      {
1240                         OldList * list = MkList();
1241                         ListAdd(list, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null));
1242
1243                         strcpy(name, "__ecerePropM_");
1244                         FullClassNameCat(name, symbol.string, false);
1245                         strcat(name, "_");
1246                         //strcat(name, propertyDef.id.string);
1247                         FullClassNameCat(name, propertyDef.id.string, true);
1248
1249                         ListAdd(list, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null));
1250                         decl = MkDeclaration(specifiers, list);
1251                      }
1252                      external = MkExternalDeclaration(decl);
1253                      ast->Insert(curExternal ? curExternal.prev : null, external);
1254                      external.symbol = propertyDef.symbol;
1255
1256                      // Setting it in the Property as well here to prevent DeclareProperty to declare it a second time...
1257                      propertyDef.symbol.externalPtr = external;
1258
1259                      if(inCompiler && prop && prop.symbol)
1260                         ((Symbol)prop.symbol).externalPtr = external;
1261                   }
1262                }
1263             }
1264          }
1265          else if(def.type == classPropertyClassDef && def.propertyDef)
1266          {
1267             PropertyDef propertyDef = def.propertyDef;
1268             ClassDef after = def;
1269             ClassDef newDef;
1270             {
1271                if(inCompiler)
1272                {
1273                   yylloc = propertyDef.loc;
1274
1275                   if(!NameSpaceContained(regClass.nameSpace, &regClass.module.privateNameSpace))
1276                      CheckPublicDataType(propertyDef.symbol.type, publicAccess, "classwide property");
1277                   else if(!symbol.isStatic)
1278                      CheckPublicDataType(propertyDef.symbol.type, privateAccess, "classwide property");
1279                }
1280
1281                // Commented this out...  Why exactly?
1282                //if(inCompiler)
1283                {
1284                   ClassFunction func;
1285                   Declarator decl;
1286                   char name[1024];
1287                   OldList * params;
1288                   if(propertyDef.getStmt && propertyDef.id)
1289                   {
1290                      Declarator declId;
1291
1292                      sprintf(name, "class::__ecereClassProp_");
1293                      FullClassNameCat(name, symbol.string, false);
1294                      strcat(name, "_Get_");
1295                      strcat(name, propertyDef.id.string);
1296
1297                      params = MkList();
1298
1299                      declId = MkDeclaratorIdentifier(MkIdentifier(name));
1300
1301                      // Class properties returns a uint64 even for struct types
1302                      /*if(propertyDef.symbol.type && propertyDef.symbol.type.kind == TypeKind::classType && propertyDef.symbol.type._class && propertyDef.symbol.type._class.registered &&
1303                         propertyDef.symbol.type._class.registered.type == structClass)
1304                      {
1305                         // ListAdd(params, MkTypeName(CopyList(propertyDef.specifiers, CopySpecifier), MkDeclaratorIdentifier(MkIdentifier("value"))));
1306                         //decl = PlugDeclarator(propertyDef.declarator, MkDeclaratorFunction(declId, params));
1307                         decl = MkDeclaratorFunction(declId, params);
1308                         ListAdd(params, MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorIdentifier(MkIdentifier("_value"))));
1309
1310                         func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, decl, null);
1311                         {
1312                            Declarator ptrDecl;
1313                            Statement body = propertyDef.getStmt;
1314                            decl = PlugDeclarator(propertyDef.declarator, MkDeclaratorFunction(declId, params));
1315                            if(!body.compound.declarations)
1316                               body.compound.declarations = MkList();
1317                            ListAdd(body.compound.declarations,
1318                               MkDeclaration(CopyList(propertyDef.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(
1319                                  ptrDecl = MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("value"))), MkInitializerAssignment(MkExpCast(MkTypeName(CopyList(propertyDef.specifiers, CopySpecifier), CopyDeclarator(propertyDef.declarator)),
1320                                     MkExpIdentifier(MkIdentifier("_value"))))))));
1321                            {
1322                               Symbol sym = ptrDecl.symbol;
1323                               sym.isParam = true;
1324                               FreeType(sym.type);
1325                               sym.type = ProcessType(propertyDef.specifiers, propertyDef.declarator);
1326                            }
1327                         }
1328                      }
1329                      else
1330                      */
1331                      {
1332                         //decl = PlugDeclarator(propertyDef.declarator, MkDeclaratorFunction(declId, params));
1333                         decl = MkDeclaratorFunction(declId, params);
1334                         //func = MkClassFunction(CopyList(propertyDef.specifiers, CopySpecifier), null, decl, null);
1335                         func = MkClassFunction(MkListOne(MkSpecifierName("uint64")), null, decl, null);
1336                      }
1337
1338                      ProcessClassFunctionBody(func, propertyDef.getStmt);
1339                      func.declarator.symbol = propertyDef.symbol;
1340                      propertyDef.symbol.externalGet = (External)func;
1341
1342                      func.dontMangle = true;
1343
1344                      newDef = MkClassDefFunction(func);
1345                      definitions.Insert(after, newDef);
1346                      after = newDef;
1347
1348                      decl = PlugDeclarator(propertyDef.declarator, MkDeclaratorFunction(null , null));
1349                      func.type = ProcessType(propertyDef.specifiers, decl);
1350                      FreeDeclarator(decl);
1351
1352                      if(func.type.returnType.kind == TypeKind::classType && func.type.returnType._class && func.type.returnType._class.registered && func.type.returnType._class.registered.type == structClass)
1353                         func.type.returnType.byReference = true;
1354
1355                      // Leverage the fact that templated types are also boxed in a 64 bit integer
1356                      func.type.returnType.passAsTemplate = true;
1357
1358                      if(inCompiler)
1359                         propertyDef.getStmt = null;
1360                      else
1361                         func.body = null;
1362                   }
1363                   if(propertyDef.setStmt && propertyDef.id)
1364                   {
1365                      Context prevCurContext;
1366                      OldList * specifiers = MkList();
1367                      Statement body = propertyDef.setStmt;
1368                      Declarator ptrDecl;
1369                      Expression e;
1370
1371                      strcpy(name, "class::__ecereClassProp_");
1372                      FullClassNameCat(name, symbol.string, false);
1373                      strcat(name, "_Set_");
1374                      strcat(name, propertyDef.id.string);
1375
1376                      params = MkList();
1377                      /*
1378                      ListAdd(params, MkTypeName(CopyList(propertyDef.specifiers, CopySpecifier),
1379                         PlugDeclarator(propertyDef.declarator,
1380                            MkDeclaratorIdentifier(MkIdentifier("value")))));
1381                      */
1382
1383                      prevCurContext = curContext;
1384                      curContext = body.compound.context;
1385
1386                      ListAdd(params, MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorIdentifier(MkIdentifier("_value"))));
1387
1388                      decl = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(name)), params);
1389                      if(!body.compound.declarations)
1390                         body.compound.declarations = MkList();
1391
1392                      if(propertyDef.symbol.type && propertyDef.symbol.type.kind == TypeKind::classType && propertyDef.symbol.type._class && propertyDef.symbol.type._class.registered &&
1393                         propertyDef.symbol.type._class.registered.type == structClass)
1394                         ptrDecl = MkDeclaratorPointer(MkPointer(null, null), PlugDeclarator(propertyDef.declarator, MkDeclaratorIdentifier(MkIdentifier("value"))));
1395                      else
1396                         ptrDecl = PlugDeclarator(propertyDef.declarator, MkDeclaratorIdentifier(MkIdentifier("value")));
1397
1398
1399                      e = MkExpIdentifier(MkIdentifier("_value"));
1400                      if(propertyDef.symbol.type.isPointerType)
1401                         e = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), e);
1402
1403                      ListAdd(body.compound.declarations,
1404                         MkDeclaration(CopyList(propertyDef.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(ptrDecl,
1405                               MkInitializerAssignment(MkExpCast(MkTypeName(CopyList(propertyDef.specifiers, CopySpecifier), CopyDeclarator(propertyDef.declarator)),
1406                               e))))));
1407
1408                      curContext = prevCurContext;
1409
1410                      {
1411                         Symbol sym = ptrDecl.symbol;
1412                         sym.isParam = true;
1413                         FreeType(sym.type);
1414                         sym.type = ProcessType(propertyDef.specifiers, propertyDef.declarator);
1415                      }
1416                      ListAdd(specifiers, MkSpecifier(VOID));
1417
1418                      func = MkClassFunction(specifiers, null, decl, null);
1419                      ProcessClassFunctionBody(func, propertyDef.setStmt);
1420                      func.dontMangle = true;
1421                      func.declarator.symbol = propertyDef.symbol;
1422                      propertyDef.symbol.externalSet = (External)func;
1423
1424                      newDef = MkClassDefFunction(func);
1425                      definitions.Insert(after, newDef);
1426                      after = newDef;
1427
1428                      if(inCompiler)
1429                         propertyDef.setStmt = null;
1430                      else
1431                         func.body = null;
1432
1433                   }
1434                }
1435             }
1436          }
1437          else if(def.type == functionClassDef && def.function.declarator)
1438          {
1439             ClassFunction func = def.function;
1440
1441             func._class = regClass;
1442             // Add ecereMethod_[class]_ to the declarator
1443             if(!func.dontMangle)
1444             {
1445                Declarator funcDecl = GetFuncDecl(func.declarator);
1446                Identifier id = GetDeclId(funcDecl);
1447                Method method;
1448
1449                if(!funcDecl.function.parameters || !funcDecl.function.parameters->first)
1450                {
1451                   if(!funcDecl.function.parameters)
1452                      funcDecl.function.parameters = MkList();
1453                   ListAdd(funcDecl.function.parameters, MkTypeName(MkListOne(MkSpecifier(VOID)), null));
1454                }
1455
1456                method = eClass_FindMethod(regClass, id.string, privateModule);
1457
1458                FreeSpecifier(id._class);
1459                id._class = null;
1460                if(inCompiler && method)
1461                {
1462                   char * newId = new char[strlen(id.string) + strlen("__ecereMethod___ecereNameSpace__") + strlen(symbol.string) + 2];
1463                   newId[0] = '\0';
1464
1465                   ProcessMethodType(method);
1466                   yylloc = def.loc;
1467                   if(!NameSpaceContained(regClass.nameSpace, &regClass.module.privateNameSpace) && method.memberAccess == publicAccess)
1468                      CheckPublicDataType(method.dataType, publicAccess, "class method");
1469                   /* HAVE TO RELAX THIS SINCE static CAN'T QUALIFY METHODS YET... (Conflict with C++ static meaning)
1470                   else if(!symbol.isStatic)
1471                      CheckPublicDataType(method.dataType, privateAccess, "class method");
1472                   */
1473
1474                   strcpy(newId, "__ecereMethod_");
1475                   FullClassNameCat(newId, symbol.string, false);
1476                   strcat(newId, "_");
1477                   strcat(newId, id.string);
1478
1479                   delete id.string;
1480
1481                   id.string = newId;
1482
1483                   if(method.type != virtualMethod)
1484                   {
1485                      if(method.symbol)
1486                      {
1487                         delete ((Symbol)method.symbol).string;
1488                         ((Symbol)method.symbol).string = CopyString(newId);
1489                      }
1490                   }
1491                }
1492             }
1493          }
1494       }
1495    }
1496
1497    if(initDeclarators != null)
1498       FreeList(initDeclarators, FreeInitDeclarator);
1499 }
1500
1501 public void PreProcessClassDefinitions()
1502 {
1503    External external, next;
1504
1505    curExternal = null;
1506
1507    if(ast)
1508    {
1509       for(external = ast->first; external; external = next)
1510       {
1511          next = external.next;
1512          curExternal = external;
1513          if(external.type == classExternal)
1514          {
1515             ClassDefinition _class = external._class;
1516             if(_class.definitions)
1517             {
1518                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, _class.loc, ast, external.prev, null, null);
1519             }
1520          }
1521          else if(external.type == declarationExternal)
1522          {
1523             Declaration declaration = external.declaration;
1524             if(declaration && declaration.type == initDeclaration)
1525             {
1526                if(declaration.specifiers)
1527                {
1528                   Specifier specifier;
1529                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
1530                   {
1531                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string &&
1532                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
1533                      {
1534                         Symbol symbol = FindClass(specifier.id.string);
1535                         if(symbol)
1536                         {
1537                            OldList * initDeclarators = null;
1538                            ExtDecl extDecl = specifier.extDeclStruct;
1539                            specifier.extDeclStruct = null;
1540                            if(inCompiler)
1541                            {
1542                               // Give the declarators away to ProcessClass
1543                               // It will include the declarators in the class if appropriate, otherwise free them
1544                               initDeclarators = declaration.declarators;
1545                               declaration.declarators = null;
1546                            }
1547                            ProcessClass((specifier.type == unionSpecifier) ? unionClass : normalClass, specifier.definitions,
1548                               symbol, specifier.baseSpecs, specifier.list, specifier.loc, ast, external.prev,
1549                               initDeclarators, extDecl);
1550                         }
1551                      }
1552                   }
1553                }
1554             }
1555             else if(declaration && inCompiler && declaration.type == defineDeclaration)
1556             {
1557                yylloc = declaration.loc;
1558                if(declaration.declMode == publicAccess)
1559                   CheckPublicExpression(declaration.exp, publicAccess);
1560                else if(declaration.declMode != staticAccess)
1561                   CheckPublicExpression(declaration.exp, privateAccess);
1562             }
1563          }
1564          else if(external.type == importExternal)
1565          {
1566             //ImportModule(external._import);
1567          }
1568          else if(inCompiler && external.type == functionExternal)
1569          {
1570             yylloc = external.function.loc;
1571             if(!external.function.type)
1572                external.function.type = ProcessType(external.function.specifiers, external.function.declarator);
1573             if(external.function.declMode == publicAccess)
1574                CheckPublicDataType(external.function.type, publicAccess, "function");
1575             else if(external.function.declMode != staticAccess)
1576                CheckPublicDataType(external.function.type, privateAccess, "function");
1577          }
1578       }
1579    }
1580 }