compiler/libec: Added safety check for structDeclarator
[sdk] / compiler / libec / src / firstPass.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 static void AddDefinitions(Class regClass, DataMember member, OldList definitions)
7 {
8    if(definitions != null)
9    {
10       ClassDef def;
11       for(def = definitions.first; def; def = def.next)
12       {
13          if(def.type == declarationClassDef)
14          {
15             Declaration decl = def.decl;
16             DataMember dataMember = null;
17             Type dataType;
18
19             if(decl.type == structDeclaration)
20             {
21                Declarator d;
22                // Add data members to the class
23                if(decl.declarators)
24                {
25                   for(d = decl.declarators->first; d; d = d.next)
26                   {
27                      Identifier declId = GetDeclId(d);
28                      if(declId)
29                      {
30                         if(regClass && regClass.type == bitClass)
31                         {
32                            Expression sizeExp = (d.type == structDeclarator) ? d.structDecl.exp : null;
33                            Expression posExp = (d.type == structDeclarator) ? d.structDecl.posExp : null;
34                            int bitSize = 0, bitPos = -1;
35                            char dataTypeString[1024] = "";
36                         
37                            if(sizeExp)
38                            {
39                               // Should this be processed/computed later?
40                               ProcessExpressionType(sizeExp);
41                               ComputeExpression(sizeExp);
42
43                               if(sizeExp.isConstant)
44                                  bitSize = strtol(sizeExp.constant, null, 0);
45                               FreeExpression(sizeExp);
46                            }
47
48                            if(posExp)
49                            {
50                               // Should this be processed/computed later?
51                               ProcessExpressionType(posExp);
52                               ComputeExpression(posExp);
53
54                               if(posExp.isConstant)
55                                  bitPos = strtol(posExp.constant, null, 0);
56                               FreeExpression(posExp);
57                            }
58
59                            if(d.type == structDeclarator)
60                            {
61                               d.structDecl.posExp = null;
62                               d.structDecl.exp = null;
63                            }
64
65                            dataType = ProcessType(decl.specifiers, d);
66                            PrintType(dataType, dataTypeString, false, true);
67
68                            //if(!eClass_FindDataMember(regClass, declId.string))
69                            {
70                               BitMember member = eClass_AddBitMember(regClass, declId.string, dataTypeString, 0, 0, def.memberAccess);
71                               if(member)
72                               {
73                                  member.size = bitSize;
74                                  member.pos = bitPos;
75                               }
76                               dataMember = (DataMember)member;
77                            }
78
79                            if(dataMember)
80                               dataMember.dataType = dataType;
81                            else
82                            {
83                               Compiler_Error($"Member with same name already exists %s in class %s\n", declId.string, regClass.name);
84                               FreeType(dataType);
85                            }
86                         }
87                         else
88                         {
89                            //if(isMember || !eClass_FindDataMember(regClass, declId.string))
90                            {
91                               //char * dataTypeString = StringFromSpecDecl(decl.specifiers, d);
92                               char typeString[1024] = "";
93                               dataType = ProcessType(decl.specifiers, d);
94                               PrintType(dataType, typeString, false, true);
95
96                               if(member)
97                               {
98                                  dataMember = eMember_AddDataMember(member, declId.string, 
99                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
100                                  if(!dataMember)
101                                     Compiler_Error($"Member with same name already exists %s in member %s\n", declId.string, member.name);
102                               }
103                               else if(regClass)
104                               {
105                                  dataMember = eClass_AddDataMember(regClass, declId.string, 
106                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
107                                  if(!dataMember)
108                                     Compiler_Error($"Member with same name already exists %s in class %s\n", declId.string, regClass.name);
109                               }
110
111                               //delete dataTypeString;
112                               if(dataMember)
113                                  dataMember.dataType = dataType;
114                               else
115                                  FreeType(dataType);
116                            }
117                         }
118                      }
119                   }
120                }
121                else if(decl.specifiers)
122                {
123                   Specifier spec;
124                   // Unnamed struct/union
125                   for(spec = decl.specifiers->first; spec; spec = spec.next)
126                   {
127                      if(spec.type == structSpecifier || spec.type == unionSpecifier)
128                      {
129                         if(spec.definitions && !spec.id)
130                         {
131                            DataMember dataMember = eMember_New((spec.type == unionSpecifier) ? unionMember : structMember, def.memberAccess);
132                            
133                            AddDefinitions(null, dataMember, spec.definitions);
134
135                            if(member)
136                            {
137                               eMember_AddMember(member, dataMember);
138                            }
139                            else
140                            {
141                               eClass_AddMember(regClass, dataMember);
142                            }
143                         }
144                         else if(spec.definitions && spec.id)
145                         {
146                            //if(isMember || !eClass_FindDataMember(regClass, spec.id.string))
147                            {
148                               Identifier id = spec.id;
149                               char typeString[1024] = "";
150
151                               spec.id = null;
152                               decl.declarators = MkListOne(MkDeclaratorIdentifier(id));
153
154                               dataType = ProcessType(decl.specifiers, null);
155                               PrintType(dataType, typeString, false, true);
156
157                               if(member)
158                               {
159                                  dataMember = eMember_AddDataMember(member, id.string, 
160                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
161                                  if(!dataMember)
162                                     Compiler_Error($"Member with same name already exists %s in member %s\n", id.string, member.name);
163                               }
164                               else
165                               {
166                                  dataMember = eClass_AddDataMember(regClass, id.string, 
167                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
168                                  if(!dataMember)
169                                     Compiler_Error($"Member with same name already exists %s in class %s\n", id.string, regClass.name);
170
171                               }
172
173                               // delete dataTypeString;
174                               if(dataMember)
175                                  dataMember.dataType = dataType;
176                               else
177                                  FreeType(dataType);
178                            }
179                         }
180                      }
181                   }
182                }
183             }
184             else if(decl.type == instDeclaration)
185             {
186                Instantiation inst = decl.inst;
187                Expression exp = inst.exp;
188                if(exp)
189                {
190                   // Add data member to the class
191                   char * string = exp.identifier.string;
192                   //if(isMember || !eClass_FindDataMember(regClass, string))
193                   {
194                      Type dataType
195                      {
196                         kind = classType;
197                         _class = inst._class.symbol; // FindClass(inst._class.name);
198                         refCount = 1;
199                      };
200                      if(member)
201                      {
202                         dataMember = eMember_AddDataMember(member, string, inst._class.name, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
203                         if(!dataMember)
204                            Compiler_Error($"Member with same name already exists %s in member %s\n", string, member.name);
205
206                      }
207                      else
208                      {
209                         dataMember = eClass_AddDataMember(regClass, string, inst._class.name, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
210                         if(!dataMember)
211                            Compiler_Error($"Member with same name already exists %s in class %s\n", string, regClass.name);
212                      }
213                      if(dataMember)
214                         dataMember.dataType = dataType;
215                      else
216                         FreeType(dataType);
217                   }
218                }
219             }
220          }
221          // TODO: Decide whether property ID should go after member ID, if so this should move back to ProcessClass
222          else if(def.type == propertyClassDef && def.propertyDef)
223          {
224             PropertyDef propertyDef = def.propertyDef;
225             Property prop;
226
227             // Register the property in the list
228             // MOVED THIS UP HERE BEFORE NEXT BLOCK BECAUSE WE NULL OUT SPECIFIERS/DECLARATORS... OK?
229             
230             char * dataTypeString = StringFromSpecDecl(propertyDef.specifiers, propertyDef.declarator);
231             prop = eClass_AddProperty(regClass, propertyDef.conversion ? null : propertyDef.id.string,
232                dataTypeString,
233                inCompiler ? propertyDef.setStmt : null, inCompiler ? propertyDef.getStmt : null, def.memberAccess);
234             delete dataTypeString;
235             if(prop)
236             {
237                if(inCompiler) prop.IsSet = (void *)propertyDef.issetStmt;
238
239                prop.compiled = false;
240                
241                // prop.symbol = propertyDef.symbol;
242                prop.symbol = Symbol
243                {
244                   string = CopyString(propertyDef.symbol.string);
245                   id = propertyDef.symbol.id;
246                   type = propertyDef.symbol.type;
247                };
248
249                /*if(propertyDef.category) 
250                {
251                   char temp[1024];
252                   ReadString(temp, propertyDef.category);
253                   prop.category = CopyString(temp);  // LEAK: To free in parsed classes...
254                }*/
255                // TODO: Support property category in parsing mode
256                ((Symbol)prop.symbol).propCategory = propertyDef.category;
257                propertyDef.category = null;
258
259                if(propertyDef.isWatchable)
260                   eProperty_Watchable(prop);
261             }
262             else
263                // TODO: What happens here?
264                printf("");
265
266
267             // Testing this... wasn't found anywhere, seems to be useful
268             // (Determining if it's a conversion property in ProcessClassFunction)
269             propertyDef.symbol._property = prop;
270
271             if(propertyDef.symbol.type)
272                propertyDef.symbol.type.refCount++;
273          }
274          else if(def.type == classPropertyClassDef && def.propertyDef)
275          {
276             PropertyDef propertyDef = def.propertyDef;
277             ClassProperty prop;
278
279             // Register the property in the list
280             // MOVED THIS UP HERE BEFORE NEXT BLOCK BECAUSE WE NULL OUT SPECIFIERS/DECLARATORS... OK?
281             
282             char * dataTypeString = StringFromSpecDecl(propertyDef.specifiers, propertyDef.declarator);
283             prop = eClass_AddClassProperty(regClass, propertyDef.id.string, dataTypeString,
284                inCompiler ? propertyDef.setStmt : null, inCompiler ? propertyDef.getStmt : null);
285
286             delete dataTypeString;
287          }
288       }
289    }
290 }
291
292 static void ProcessClass(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues, Location loc, OldList defs, void * after, OldList initDeclarators, AccessMode declMode)
293 {
294    Class regClass;
295    ClassDef def;
296    bool redefinition = false;
297
298    regClass = eSystem_FindClass(privateModule /*__thisModule*/, symbol.string);
299    if(regClass && !regClass.internalDecl)
300    {
301       if(symbol.parent || (Symbol)globalContext.classes.root == symbol)
302       {
303          globalContext.classes.Remove((BTNode)symbol);
304          excludedSymbols->Add(symbol);
305       }
306       redefinition = true;
307       if(inCompiler)
308       {
309          yylloc = loc;
310          Compiler_Error($"redefinition of class %s\n", symbol.string /*_class._class.name*/);
311          return;
312       }
313    }
314    else
315    {
316       char baseName[1024] = "";
317       bool unitType = false;
318       bool wouldBeEnum = false;
319       AccessMode inheritanceAccess = publicAccess;
320
321       if(baseSpecs != null)
322       {
323          Type baseType = ProcessType(baseSpecs, null);
324          PrintType(baseType, baseName, false, true);
325          if(baseType.kind == TypeKind::classType)
326          {
327             if(baseType._class.registered && classType == normalClass)
328             {
329                if(baseType._class.registered.type == unitClass)
330                   classType = unitClass;
331                else if(baseType._class.registered.type == bitClass)
332                   classType = bitClass;
333                else if(baseType._class.registered.type == noHeadClass)
334                   classType = noHeadClass;
335                else if(baseType._class.registered.type == enumClass)
336                {
337                   wouldBeEnum = true;
338                   //classType = enumClass;
339                }
340             }
341          }
342          else if(baseType.kind == structType || baseType.kind == unionType) 
343          {
344             classType = noHeadClass;
345             baseName[0] = '\0';
346          }
347          else 
348             unitType = true;
349          FreeType(baseType);
350
351          if(((Specifier)baseSpecs.first).type == baseSpecifier && ((Specifier)baseSpecs.first).specifier == PRIVATE)
352             inheritanceAccess = privateAccess;
353       }
354
355       // If there's any struct declaration in a unit data type, it means this is a bit class
356       if(classType == normalClass)
357       {
358          if(unitType) classType = unitClass;
359          if(definitions != null)
360          {
361             for(def = definitions.first; def; def = def.next)
362             {
363                if(def.type == declarationClassDef)
364                {
365                   Declaration decl = def.decl;
366                   if(decl.type == structDeclaration)
367                   {
368                      if(unitType)
369                      {
370                         classType = bitClass;
371                         break;
372                      }
373                      if(decl.declarators)
374                      {
375                         Declarator d;
376
377                         for(d = decl.declarators->first; d; d = d.next)
378                         {
379                            if(d.structDecl.exp)
380                            {
381                               classType = bitClass;
382                               break;
383                            }
384                         }
385                         if(d) break;
386                      }
387                   }
388                }
389             }
390          }
391       }
392       if(classType == normalClass && wouldBeEnum) classType = enumClass;
393
394       regClass = symbol.registered = eSystem_RegisterClass((classType == unionClass) ? structClass : classType,
395          symbol.string, baseName[0] ? baseName : null, 0, 0, null, null, privateModule, buildingECERECOMModule ? baseSystemAccess : declMode /*publicAccess*/, inheritanceAccess);
396
397       // HI DANGER: TESTING THIS
398       if(regClass)
399          regClass.symbol = symbol;
400    }
401
402    // First check if there's any declaration or instantiations, we'll need a struct
403    if(!redefinition)
404    {
405       if(classType == unionClass)
406       {
407          DataMember unionMember = eMember_New(DataMemberType::unionMember, publicAccess);
408          AddDefinitions(regClass, unionMember, definitions);
409          eClass_AddMember(regClass, unionMember);
410       }
411       else
412          AddDefinitions(regClass, null, definitions);
413    }
414
415    // Do the functions
416    if(definitions != null)
417    {
418       for(def = definitions.first; def; def = def.next)
419       {
420          if(def.type == functionClassDef && def.function.declarator)
421          {
422             ClassFunction func = def.function;
423
424             func._class = regClass;
425             // Add ecereMethod_[class]_ to the declarator
426             if(!redefinition && !func.dontMangle)
427             {
428                Declarator funcDecl = GetFuncDecl(func.declarator);
429                Identifier id = GetDeclId(funcDecl);
430                Method method;               
431                         
432                if(func.isVirtual)
433                {
434                   char * typeString = StringFromSpecDecl(func.specifiers, func.declarator);
435                   method = eClass_AddVirtualMethod(regClass, id.string, typeString, inCompiler ? func.declarator.symbol : null, def.memberAccess);
436                   delete typeString;
437                }
438                else
439                {
440                   char * typeString = StringFromSpecDecl(func.specifiers, func.declarator);
441                   method = eClass_AddMethod(regClass, id.string, typeString, 
442                      inCompiler ? func.declarator.symbol : null, def.memberAccess);
443                   if(!method)
444                      Compiler_Error($"Redefinition of method %s in class %s\n", id.string, regClass.name);
445                   delete typeString;
446                }
447                if(method && (method.type != virtualMethod || method._class == regClass))
448                {
449                   //method.symbol = func.declarator.symbol;
450
451                   // Make a copy here...
452                   method.symbol = Symbol
453                   {
454                      string = CopyString(func.declarator.symbol.string);
455                      id = func.declarator.symbol.id;
456                      type = func.declarator.symbol.type;
457                      method = method;
458                   };
459                   if(func.declarator.symbol.type)
460                      func.declarator.symbol.type.refCount++;
461
462                   func.declarator.symbol.method = method;
463                }
464                else
465                {
466                   /*
467                   method.symbol = Symbol
468                   {
469                      string = CopyString(func.declarator.symbol.string);
470                      id = func.declarator.symbol.id;
471                      type = func.declarator.symbol.type;
472                      method = method;
473                   };
474                   if(func.declarator.symbol.type)
475                      func.declarator.symbol.type.refCount++;
476                   */
477                   func.declarator.symbol.method = method;
478                }
479             }
480          }
481       }
482    }
483    if(regClass && symbol.templateParams)
484    {
485       TemplateParameter param;
486       // Add template parameters here
487       for(param = symbol.templateParams->first; param; param = param.next)
488       {
489          ClassTemplateArgument defaultArg { };
490          if(param.defaultArgument)
491          {
492             switch(param.type)
493             {
494                case type:
495                   defaultArg.dataTypeString = 
496                      StringFromSpecDecl(param.defaultArgument.templateDatatype.specifiers, param.defaultArgument.templateDatatype.decl);
497                   break;
498                case identifier:
499                {
500                   char memberString[1024];
501                   memberString[0] = '\0';
502
503                   if(param.defaultArgument.identifier._class)
504                   {
505                      if(param.defaultArgument.identifier._class.type == templateTypeSpecifier)
506                      {
507                         if(param.defaultArgument.identifier._class.templateParameter)
508                            strcpy(memberString, param.defaultArgument.identifier._class.templateParameter.identifier.string);
509                      }
510                      else
511                      {
512                         if(param.defaultArgument.identifier._class.name)
513                            strcpy(memberString, param.defaultArgument.identifier._class.name);
514                      }
515                   }
516                   
517                   if(memberString[0])
518                   {
519                      strcat(memberString, "::");
520                   }
521                   strcat(memberString, param.defaultArgument.identifier.string);
522                   defaultArg.memberString = CopyString(memberString);
523                   break;
524                }
525                case expression:
526                {
527                   Operand op;
528                   param.defaultArgument.expression.destType = ProcessType(param.dataType.specifiers, param.dataType.decl);
529                   ProcessExpressionType(param.defaultArgument.expression);
530                   ComputeExpression(param.defaultArgument.expression);
531                   op = GetOperand(param.defaultArgument.expression);
532                   defaultArg.expression.ui64 = op.ui64;
533                   break;
534                }
535             }
536          }
537          if(param.type == identifier)
538          {
539             eClass_AddTemplateParameter(regClass, param.identifier.string, identifier, (void *)param.memberType, defaultArg);
540          }
541          else
542          {
543             char * typeString = param.dataType ? StringFromSpecDecl(param.dataType.specifiers, param.dataType.decl) : null;
544             eClass_AddTemplateParameter(regClass, param.identifier.string, param.type, typeString, defaultArg);
545             delete typeString;
546          }
547          if(param.type == type || param.type == identifier)
548             delete defaultArg.dataTypeString;
549
550       }
551       eClass_DoneAddingTemplateParameters(regClass);
552    }
553 }
554
555 extern External curExternal;
556
557 public void PrePreProcessClassDefinitions()
558 {
559    External external, next;
560
561    curExternal = null;
562
563    if(ast)
564    {
565       for(external = ast->first; external; external = next)
566       {
567          next = external.next;
568          curExternal = external;
569          if(external.type == classExternal)
570          {
571             ClassDefinition _class = external._class;
572             if(_class.definitions && (!_class.symbol.registered || !inCompiler))
573             {
574                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, _class.loc, ast, external.prev, null, _class.declMode);
575                _class.symbol.isStatic = _class.declMode == staticAccess;
576             }
577          }
578          else if(external.type == declarationExternal)
579          {
580             Declaration declaration = external.declaration;
581             if(declaration.type == initDeclaration)
582             {
583                if(declaration.specifiers)
584                {
585                   Specifier specifier;
586                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
587                   {
588                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string && 
589                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
590                      {
591                         Symbol type = FindType(globalContext, specifier.id.string);
592                         Symbol symbol = FindClass(specifier.id.string);
593                         if(type)
594                         {
595                            declaration.declMode = defaultAccess;
596                            if(symbol)
597                            {
598                               globalContext.classes.Remove((BTNode)symbol);
599                               excludedSymbols->Add(symbol);
600                            }
601                         }
602                         else if(symbol && !symbol.registered)
603                         {
604                            ClassType classType;
605
606                            if(specifier.type == enumSpecifier)
607                               classType = enumClass;
608                            else if(specifier.type == unionSpecifier)
609                               classType = unionClass;
610                            else
611                               classType = structClass;
612                            ProcessClass(classType, specifier.definitions, symbol, specifier.baseSpecs, specifier.list, specifier.loc, ast, external.prev, declaration.declarators, declaration.declMode);
613                            symbol.isStatic = declaration.declMode == staticAccess;
614                         }
615                      }
616                   }
617                }
618             }
619          }
620          else if(external.type == importExternal)
621          {
622             //ImportModule(external._import);
623          }
624       }
625
626
627       // Update templated classes
628       {
629          for(external = ast->first; external; external = external.next)
630          {
631             if(external.type == classExternal)
632             {
633                ClassDefinition _class = external._class;
634                if(_class.symbol)
635                {
636                   OldLink link;
637                   for(link = _class.symbol.templatedClasses.first; link; link = link.next)
638                   {
639                      Symbol symbol = link.data;
640                      symbol.registered = eSystem_FindClass(privateModule, symbol.string);
641                   }
642                }
643             }
644             else if(external.type == declarationExternal)
645             {
646                Declaration declaration = external.declaration;
647                if(declaration.type == initDeclaration)
648                {
649                   if(declaration.specifiers)
650                   {
651                      Specifier specifier;
652                      for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
653                      {
654                         if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string && 
655                            (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
656                         {
657                            Symbol type = FindType(globalContext, specifier.id.string);
658                            Symbol symbol = FindClass(specifier.id.string);
659                            if(type)
660                            {
661                            }
662                            else if(symbol)
663                            {
664                               OldLink link;
665                               for(link = symbol.templatedClasses.first; link; link = link.next)
666                               {
667                                  Symbol tplSymbol = link.data;
668                                  tplSymbol.registered = eSystem_FindClass(privateModule, tplSymbol.string);
669                                  tplSymbol.module = symbol.module ? symbol.module : mainModule;
670                               }
671                            }
672                         }
673                      }
674                   }
675                }
676             }
677          } 
678       }
679    }
680 }