Browse Source

* synchronized with trunk

git-svn-id: branches/wasm@46798 -
nickysn 4 years ago
parent
commit
d7559d7a38

+ 7 - 0
.gitattributes

@@ -13562,6 +13562,13 @@ tests/test/cg/obj/freebsd/x86_64/tcext3.o -text
 tests/test/cg/obj/freebsd/x86_64/tcext4.o -text
 tests/test/cg/obj/freebsd/x86_64/tcext4.o -text
 tests/test/cg/obj/freebsd/x86_64/tcext5.o -text
 tests/test/cg/obj/freebsd/x86_64/tcext5.o -text
 tests/test/cg/obj/freebsd/x86_64/tcext6.o -text
 tests/test/cg/obj/freebsd/x86_64/tcext6.o -text
+tests/test/cg/obj/freertos/xtensa-call0/cpptcl1.o -text
+tests/test/cg/obj/freertos/xtensa-call0/cpptcl2.o -text
+tests/test/cg/obj/freertos/xtensa-call0/ctest.o -text
+tests/test/cg/obj/freertos/xtensa-call0/tcext3.o -text
+tests/test/cg/obj/freertos/xtensa-call0/tcext4.o -text
+tests/test/cg/obj/freertos/xtensa-call0/tcext5.o -text
+tests/test/cg/obj/freertos/xtensa-call0/tcext6.o -text
 tests/test/cg/obj/freertos/xtensa-windowed/cpptcl1.o -text
 tests/test/cg/obj/freertos/xtensa-windowed/cpptcl1.o -text
 tests/test/cg/obj/freertos/xtensa-windowed/cpptcl2.o -text
 tests/test/cg/obj/freertos/xtensa-windowed/cpptcl2.o -text
 tests/test/cg/obj/freertos/xtensa-windowed/ctest.o -text
 tests/test/cg/obj/freertos/xtensa-windowed/ctest.o -text

+ 47 - 14
compiler/ncgutil.pas

@@ -594,26 +594,59 @@ implementation
           paraloc: PCGParalocation;
           paraloc: PCGParalocation;
           loc: tlocation;
           loc: tlocation;
           regtype: tregistertype;
           regtype: tregistertype;
-          reg: tregister;
-          size: tcgint;
+          reg,reg2: tregister;
+          size,regsize: tcgint;
         begin
         begin
           tparavarsym(sym).paraloc[calleeside].get_location(loc);
           tparavarsym(sym).paraloc[calleeside].get_location(loc);
           size:=tparavarsym(sym).paraloc[calleeside].IntSize;
           size:=tparavarsym(sym).paraloc[calleeside].IntSize;
           paraloc:=tparavarsym(sym).paraloc[calleeside].Location;
           paraloc:=tparavarsym(sym).paraloc[calleeside].Location;
-          reg:=sym.initialloc.register;
+{$if defined(cpu64bitalu)}
+          if sym.initialloc.size in [OS_128,OS_S128] then
+{$else}
+          if sym.initialloc.size in [OS_64,OS_S64] then
+{$endif defined(cpu64bitalu)}
+            begin
+              if target_info.endian=endian_little then
+                begin
+                  reg:=sym.initialloc.register;
+                  reg2:=sym.initialloc.registerhi;
+                end
+              else
+                begin
+                  reg:=sym.initialloc.registerhi;
+                  reg2:=sym.initialloc.register;
+                end;
+            end
+          else
+            begin
+              reg:=sym.initialloc.register;
+              reg2:=NR_NO;
+            end;
           regtype:=getregtype(reg);
           regtype:=getregtype(reg);
-          repeat
-            loc.reference.offset:=paraloc^.reference.offset;
-            cg.rg[regtype].set_reg_initial_location(reg,loc.reference);
-            dec(size,tcgsize2size[paraloc^.Size]);
+          while true do
+            begin
+              cg.rg[regtype].set_reg_initial_location(reg,loc.reference);
+              regsize:=tcgsize2size[reg_cgsize(reg)];
+              dec(size,regsize);
+              if size<=0 then
+                break;
+              if paraloc<>nil then
+                paraloc:=paraloc^.Next;
+              if paraloc<>nil then
+                loc.reference.offset:=paraloc^.reference.offset
+              else
+                inc(loc.reference.offset,regsize);
 {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
 {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
-            if cg.has_next_reg[getsupreg(reg)] then
-              reg:=cg.GetNextReg(reg)
-            else
+              if cg.has_next_reg[getsupreg(reg)] then
+                reg:=cg.GetNextReg(reg)
+              else
 {$endif}
 {$endif}
-              reg:=sym.initialloc.registerhi;
-            paraloc:=paraloc^.Next;
-          until size=0;
+                begin
+                  if reg=reg2 then
+                    internalerror(2020090502);
+                  reg:=reg2;
+                end;
+            end;
         end;
         end;
 
 
       var
       var
@@ -705,7 +738,7 @@ implementation
         { Notify the register allocator about memory location of
         { Notify the register allocator about memory location of
           the register which holds a value of a stack parameter }
           the register which holds a value of a stack parameter }
         if (sym.typ=paravarsym) and
         if (sym.typ=paravarsym) and
-          (tparavarsym(sym).paraloc[calleeside].Location^.Loc=LOC_REFERENCE) then
+           paramanager.param_use_paraloc(tparavarsym(sym).paraloc[calleeside]) then
           set_para_regvar_initial_location;
           set_para_regvar_initial_location;
       end;
       end;
 
 

+ 1 - 1
compiler/psub.pas

@@ -1173,7 +1173,7 @@ implementation
           with an internal error, so this switch is not enabled by default yet. To overcome this,
           with an internal error, so this switch is not enabled by default yet. To overcome this,
           multipass compilation of subroutines must be supported
           multipass compilation of subroutines must be supported
         }
         }
-        if (target_info.abi=abi_xtensa_windowed) and (procdef.stack_tainting_parameter(calleeside)) then
+        if procdef.stack_tainting_parameter(calleeside) then
           begin
           begin
             include(flags,pi_estimatestacksize);
             include(flags,pi_estimatestacksize);
             set_first_temp_offset;
             set_first_temp_offset;

+ 1 - 1
compiler/rgobj.pas

@@ -2136,7 +2136,7 @@ unit rgobj;
         supreg: TSuperRegister;
         supreg: TSuperRegister;
       begin
       begin
         supreg:=getsupreg(reg);
         supreg:=getsupreg(reg);
-        if supreg>=maxreg then
+        if (supreg<first_imaginary) or (supreg>=maxreg) then
           internalerror(2020090501);
           internalerror(2020090501);
         alloc_spillinfo(supreg+1);
         alloc_spillinfo(supreg+1);
         spillinfo[supreg].spilllocation:=ref;
         spillinfo[supreg].spilllocation:=ref;

+ 2 - 0
compiler/xtensa/cpupara.pas

@@ -158,6 +158,8 @@ unit cpupara;
             begin
             begin
               curintreg:=RS_A2;
               curintreg:=RS_A2;
               maxintreg:=RS_A7;
               maxintreg:=RS_A7;
+              if (side=calleeside) and (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+                cur_stack_offset:=(p as tcpuprocdef).total_stackframe_size;
             end;
             end;
           else
           else
             Internalerror(2020031404);
             Internalerror(2020031404);

+ 2 - 1
compiler/xtensa/cpupi.pas

@@ -84,7 +84,8 @@ unit cpupi;
             callins:=A_CALL0;
             callins:=A_CALL0;
             callxins:=A_CALLX0;
             callxins:=A_CALLX0;
             maxcall:=0;
             maxcall:=0;
-            framepointer:=NR_FRAME_POINTER_REG;
+            { we do not use a frame pointer }
+            framepointer:=NR_STACK_POINTER_REG;
           end;
           end;
       end;
       end;
 
 

+ 167 - 55
packages/fcl-passrc/src/pasresolver.pp

@@ -1791,7 +1791,7 @@ type
     function GetTVarRec(El: TPasArrayType): TPasRecordType; virtual;
     function GetTVarRec(El: TPasArrayType): TPasRecordType; virtual;
     function FindDefaultConstructor(aClass: TPasClassType): TPasConstructor; virtual;
     function FindDefaultConstructor(aClass: TPasClassType): TPasConstructor; virtual;
     function GetTypeInfoParamType(Param: TPasExpr;
     function GetTypeInfoParamType(Param: TPasExpr;
-      out ParamResolved: TPasResolverResult; LoType: boolean): TPasType; virtual;
+      out ParamResolved: TPasResolverResult; LoType: boolean): TPasType; virtual; // returns type of param in typeinfo(param)
   protected
   protected
     // constant evaluation
     // constant evaluation
     fExprEvaluator: TResExprEvaluator;
     fExprEvaluator: TResExprEvaluator;
@@ -1840,8 +1840,7 @@ type
       GenTempl: TPasGenericTemplateType; ErrorPos: TPasElement);
       GenTempl: TPasGenericTemplateType; ErrorPos: TPasElement);
     function CreateSpecializedItem(El: TPasElement; GenericEl: TPasElement;
     function CreateSpecializedItem(El: TPasElement; GenericEl: TPasElement;
       const ParamsResolved: TPasTypeArray): TPRSpecializedItem; virtual;
       const ParamsResolved: TPasTypeArray): TPRSpecializedItem; virtual;
-    function CreateSpecializedTypeName(SpecializedItems: TObjectList;
-      Item: TPRSpecializedItem): string; virtual;
+    function CreateSpecializedTypeName(Item: TPRSpecializedItem): string; virtual;
     procedure InitSpecializeScopes(El: TPasElement; out State: TScopeStashState); virtual;
     procedure InitSpecializeScopes(El: TPasElement; out State: TScopeStashState); virtual;
     procedure RestoreSpecializeScopes(const State: TScopeStashState); virtual;
     procedure RestoreSpecializeScopes(const State: TScopeStashState); virtual;
     procedure SpecializeGenericIntf(SpecializedItem: TPRSpecializedItem); virtual;
     procedure SpecializeGenericIntf(SpecializedItem: TPRSpecializedItem); virtual;
@@ -2473,8 +2472,11 @@ function ProcNeedsBody(Proc: TPasProcedure): boolean;
 function ProcHasGroupOverload(Proc: TPasProcedure): boolean;
 function ProcHasGroupOverload(Proc: TPasProcedure): boolean;
 procedure ClearHelperList(var List: TPRHelperEntryArray);
 procedure ClearHelperList(var List: TPRHelperEntryArray);
 function ChompDottedIdentifier(const Identifier: string): string;
 function ChompDottedIdentifier(const Identifier: string): string;
-function FirstDottedIdentifier(const Identifier: string): string;
+function FirstDottedIdentifier(const Identifier: string): string; // without <>
+function LastDottedIdentifier(const Identifier: string): string; // without <>
 function IsDottedIdentifierPrefix(const Prefix, Identifier: string): boolean;
 function IsDottedIdentifierPrefix(const Prefix, Identifier: string): boolean;
+function GetFirstDotPos(const Identifier: string): integer;
+function GetLastDotPos(const Identifier: string): integer;
 {$IF FPC_FULLVERSION<30101}
 {$IF FPC_FULLVERSION<30101}
 function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDots: Boolean = False): Boolean;
 function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDots: Boolean = False): Boolean;
 {$ENDIF}
 {$ENDIF}
@@ -2943,14 +2945,18 @@ end;
 
 
 function ChompDottedIdentifier(const Identifier: string): string;
 function ChompDottedIdentifier(const Identifier: string): string;
 var
 var
-  p: Integer;
+  p, Lvl: Integer;
 begin
 begin
   Result:=Identifier;
   Result:=Identifier;
   p:=length(Identifier);
   p:=length(Identifier);
+  Lvl:=0;
   while (p>0) do
   while (p>0) do
     begin
     begin
-    if Identifier[p]='.' then
-      break;
+    case Identifier[p] of
+    '.': if Lvl=0 then break;
+    '>': inc(Lvl);
+    '<': dec(Lvl);
+    end;
     dec(p);
     dec(p);
     end;
     end;
   Result:=LeftStr(Identifier,p-1);
   Result:=LeftStr(Identifier,p-1);
@@ -2958,13 +2964,41 @@ end;
 
 
 function FirstDottedIdentifier(const Identifier: string): string;
 function FirstDottedIdentifier(const Identifier: string): string;
 var
 var
-  p: SizeInt;
+  p, l: SizeInt;
 begin
 begin
-  p:=Pos('.',Identifier);
-  if p<1 then
-    Result:=Identifier
-  else
-    Result:=LeftStr(Identifier,p-1);
+  p:=1;
+  l:=length(Identifier);
+  repeat
+    if p>l then
+      exit(Identifier)
+    else if Identifier[p] in ['<','.'] then
+      exit(LeftStr(Identifier,p-1))
+    else
+      inc(p);
+  until false;
+end;
+
+function LastDottedIdentifier(const Identifier: string): string;
+var
+  p, Lvl, EndP: Integer;
+begin
+  p:=length(Identifier);
+  EndP:=p;
+  Lvl:=0;
+  while (p>0) do
+    begin
+    case Identifier[p] of
+    '.': if Lvl=0 then break;
+    '>': inc(Lvl);
+    '<':
+      begin
+      dec(Lvl);
+      EndP:=p-1;
+      end;
+    end;
+    dec(p);
+    end;
+  Result:=copy(Identifier,p+1,EndP-p);
 end;
 end;
 
 
 function IsDottedIdentifierPrefix(const Prefix, Identifier: string): boolean;
 function IsDottedIdentifierPrefix(const Prefix, Identifier: string): boolean;
@@ -2978,6 +3012,43 @@ begin
   Result:=(length(Identifier)=l) or (Identifier[l+1]='.');
   Result:=(length(Identifier)=l) or (Identifier[l+1]='.');
 end;
 end;
 
 
+function GetFirstDotPos(const Identifier: string): integer;
+var
+  l: SizeInt;
+  Lvl: Integer;
+begin
+  Result:=1;
+  l:=length(Identifier);
+  Lvl:=0;
+  repeat
+    if Result>l then
+      exit(-1);
+    case Identifier[Result] of
+    '.': if Lvl=0 then exit;
+    '<': inc(Lvl);
+    '>': dec(Lvl);
+    end;
+    inc(Result);
+  until false;
+end;
+
+function GetLastDotPos(const Identifier: string): integer;
+var
+  Lvl: Integer;
+begin
+  Result:=length(Identifier);
+  Lvl:=0;
+  while (Result>0) do
+    begin
+    case Identifier[Result] of
+    '.': if Lvl=0 then exit;
+    '>': inc(Lvl);
+    '<': dec(Lvl);
+    end;
+    dec(Result);
+    end;
+end;
+
 function DotExprToName(Expr: TPasExpr): string;
 function DotExprToName(Expr: TPasExpr): string;
 var
 var
   C: TClass;
   C: TClass;
@@ -6931,7 +7002,7 @@ begin
         RaiseMsg(20181231150404,nXCannotHaveParameters,sXCannotHaveParameters,[GetElementTypeName(Proc)],Proc);
         RaiseMsg(20181231150404,nXCannotHaveParameters,sXCannotHaveParameters,[GetElementTypeName(Proc)],Proc);
       end;
       end;
 
 
-    HasDots:=Pos('.',ProcName)>1;
+    HasDots:=GetFirstDotPos(ProcName)>0;
 
 
     if Proc.Parent is TPasClassType then
     if Proc.Parent is TPasClassType then
       begin
       begin
@@ -7309,7 +7380,6 @@ var
   DeclProc: TPasProcedure;
   DeclProc: TPasProcedure;
   ClassOrRecScope: TPasClassOrRecordScope;
   ClassOrRecScope: TPasClassOrRecordScope;
   SelfArg: TPasArgument;
   SelfArg: TPasArgument;
-  p: Integer;
   SelfType, LoSelfType: TPasType;
   SelfType, LoSelfType: TPasType;
   LastNamePart: TProcedureNamePart;
   LastNamePart: TProcedureNamePart;
 begin
 begin
@@ -7336,11 +7406,7 @@ begin
   else
   else
     begin
     begin
     // remove path from ProcName
     // remove path from ProcName
-    repeat
-      p:=Pos('.',ProcName);
-      if p<1 then break;
-      Delete(ProcName,1,p);
-    until false;
+    ProcName:=LastDottedIdentifier(ProcName);
     end;
     end;
 
 
   if ImplProcScope.DeclarationProc=nil then
   if ImplProcScope.DeclarationProc=nil then
@@ -11920,7 +11986,7 @@ begin
       AddGenericTemplateIdentifiers(TypeParams,Scope);
       AddGenericTemplateIdentifiers(TypeParams,Scope);
       end;
       end;
   end else if TypeParams<>nil then
   end else if TypeParams<>nil then
-    RaiseNotYetImplemented(20190812215851,El);
+    RaiseNotYetImplemented(20190812215851,El); // anonymous generic array type
 end;
 end;
 
 
 procedure TPasResolver.AddRecordType(El: TPasRecordType; TypeParams: TFPList);
 procedure TPasResolver.AddRecordType(El: TPasRecordType; TypeParams: TFPList);
@@ -12412,7 +12478,7 @@ begin
 
 
   // Note: El.ProcType is nil !  It is parsed later.
   // Note: El.ProcType is nil !  It is parsed later.
 
 
-  HasDot:=Pos('.',ProcName)>1;
+  HasDot:=GetFirstDotPos(ProcName)>1;
   if (TypeParams<>nil) then
   if (TypeParams<>nil) then
     if HasDot<>(TypeParams.Count>1) then
     if HasDot<>(TypeParams.Count>1) then
       RaiseNotYetImplemented(20190818093923,El);
       RaiseNotYetImplemented(20190818093923,El);
@@ -12485,14 +12551,14 @@ begin
       Level:=0;
       Level:=0;
       repeat
       repeat
         inc(Level);
         inc(Level);
-        p:=Pos('.',ProcName);
+        p:=GetFirstDotPos(ProcName);
         if p<1 then
         if p<1 then
           begin
           begin
           if ClassOrRecType=nil then
           if ClassOrRecType=nil then
             RaiseInternalError(20161013170829);
             RaiseInternalError(20161013170829);
           break;
           break;
           end;
           end;
-        aClassName:=LeftStr(ProcName,p-1);
+        aClassName:=FirstDottedIdentifier(ProcName);
         Delete(ProcName,1,p);
         Delete(ProcName,1,p);
         TypeParamCount:=0;
         TypeParamCount:=0;
         if TypeParams<>nil then
         if TypeParams<>nil then
@@ -16503,7 +16569,7 @@ var
   begin
   begin
     // insert in front of currently parsed elements
     // insert in front of currently parsed elements
     // beware: specializing an element can create other specialized elements
     // beware: specializing an element can create other specialized elements
-    // add behind last specialized element of this GenericEl
+    // add behind last finished specialized element of this GenericEl
     // for example: A = class(B<C<D>>)
     // for example: A = class(B<C<D>>)
     // =>
     // =>
     //  D
     //  D
@@ -16548,15 +16614,6 @@ var
       else
       else
         break;
         break;
       end;
       end;
-
-    //if i<0 then
-    //  begin
-    //  {$IF defined(VerbosePasResolver) or defined(VerbosePas2JS)}
-    //  writeln('InsertBehind Generic=',GetObjName(GenericEl),' Last=',GetObjName(Last));
-    //  //for i:=0 to List.Count-1 do writeln('  ',GetObjName(TObject(List[i])));
-    //  {$ENDIF}
-    //  i:=List.Count-1;
-    //  end;
     List.Insert(i+1,NewEl);
     List.Insert(i+1,NewEl);
   end;
   end;
 
 
@@ -16571,8 +16628,6 @@ var
   ProcItem: TPRSpecializedProcItem;
   ProcItem: TPRSpecializedProcItem;
 begin
 begin
   Result:=nil;
   Result:=nil;
-  if Pos('$G',GenericEl.Name)>0 then
-    RaiseNotYetImplemented(20190813003729,El);
 
 
   SrcModule:=GenericEl.GetModule;
   SrcModule:=GenericEl.GetModule;
   SrcModuleScope:=SrcModule.CustomData as TPasModuleScope;
   SrcModuleScope:=SrcModule.CustomData as TPasModuleScope;
@@ -16602,7 +16657,7 @@ begin
   Result.Params:=ParamsResolved;
   Result.Params:=ParamsResolved;
   Result.Index:=SpecializedItems.Count;
   Result.Index:=SpecializedItems.Count;
   SpecializedItems.Add(Result);
   SpecializedItems.Add(Result);
-  NewName:=CreateSpecializedTypeName(SpecializedItems,Result);
+  NewName:=CreateSpecializedTypeName(Result);
   NewClass:=TPTreeElement(GenericEl.ClassType);
   NewClass:=TPTreeElement(GenericEl.ClassType);
   NewParent:=GenericEl.Parent;
   NewParent:=GenericEl.Parent;
   NewEl:=TPasElement(NewClass.Create(NewName,NewParent));
   NewEl:=TPasElement(NewClass.Create(NewName,NewParent));
@@ -16631,10 +16686,66 @@ begin
     SpecializeGenericImpl(Result);
     SpecializeGenericImpl(Result);
 end;
 end;
 
 
-function TPasResolver.CreateSpecializedTypeName(SpecializedItems: TObjectList;
-  Item: TPRSpecializedItem): string;
+function TPasResolver.CreateSpecializedTypeName(Item: TPRSpecializedItem): string;
+
+  function GetTypeName(aType: TPasType): string; forward;
+
+  function GetSpecParams(Item: TPRSpecializedItem): string;
+  var
+    i: Integer;
+  begin
+    Result:='<';
+    for i:=0 to length(Item.Params)-1 do
+      begin
+      if i>0 then Result:=Result+',';
+      Result:=Result+GetTypeName(Item.Params[i]);
+      end;
+    Result:=Result+'>';
+  end;
+
+  function GetTypeName(aType: TPasType): string;
+  var
+    Arr: TPasArrayType;
+    ElType: TPasType;
+    ChildItem: TPRSpecializedItem;
+  begin
+    if aType.Name='' then
+      begin
+      if aType is TPasArrayType then
+        begin
+        // e.g. TBird<array of word>
+        Result:='array of ';
+        Arr:=TPasArrayType(aType);
+        if length(Arr.Ranges)>0 then
+          RaiseNotYetImplemented(20200905173026,Item.FirstSpecialize);
+        ElType:=ResolveAliasType(Arr.ElType,false);
+        if ElType is TPasArrayType then
+          RaiseNotYetImplemented(20200905173159,Arr,'multidimensional anonymous array as generic param');
+        Result:=Result+GetTypeName(ElType);
+        end
+      else
+        RaiseNotYetImplemented(20200905173241,aType);
+      end
+    else
+      begin
+      if aType.Parent is TPasType then
+        Result:=GetTypeName(TPasType(aType.Parent))
+      else if aType is TPasUnresolvedSymbolRef then
+        Result:='System'
+      else
+        Result:=aType.GetModule.Name;
+      Result:=Result+'.'+aType.Name;
+      if aType.CustomData is TPasGenericScope then
+        begin
+        ChildItem:=TPasGenericScope(aType.CustomData).SpecializedFromItem;
+        if ChildItem<>nil then
+          Result:=Result+GetSpecParams(ChildItem);
+        end;
+      end;
+  end;
+
 begin
 begin
-  Result:=Item.GenericEl.Name+'$G'+IntToStr(SpecializedItems.Count);
+  Result:=Item.GenericEl.Name+GetSpecParams(Item);
 end;
 end;
 
 
 procedure TPasResolver.InitSpecializeScopes(El: TPasElement; out
 procedure TPasResolver.InitSpecializeScopes(El: TPasElement; out
@@ -17063,12 +17174,11 @@ begin
     if SpecClassOrRecScope=nil then
     if SpecClassOrRecScope=nil then
       RaiseNotYetImplemented(20190921221839,SpecDeclProc);
       RaiseNotYetImplemented(20190921221839,SpecDeclProc);
     NewImplProcName:=GenImplProc.Name;
     NewImplProcName:=GenImplProc.Name;
-    p:=length(NewImplProcName);
-    while (p>0) and (NewImplProcName[p]<>'.') do dec(p);
-    if p=0 then
+    LastDotP:=GetLastDotPos(NewImplProcName);
+    if LastDotP<1 then
       RaiseNotYetImplemented(20190921221730,GenImplProc);
       RaiseNotYetImplemented(20190921221730,GenImplProc);
     // has classname -> replace generic classname with specialized classname
     // has classname -> replace generic classname with specialized classname
-    LastDotP:=p;
+    p:=LastDotP;
     while (p>1) and (NewImplProcName[p-1]<>'.') do dec(p);
     while (p>1) and (NewImplProcName[p-1]<>'.') do dec(p);
     OldClassname:=copy(NewImplProcName,p,LastDotP-p);
     OldClassname:=copy(NewImplProcName,p,LastDotP-p);
     GenClassOrRec:=GenDeclProc.Parent as TPasMembersType;
     GenClassOrRec:=GenDeclProc.Parent as TPasMembersType;
@@ -17080,8 +17190,7 @@ begin
     begin
     begin
     // use classname of GenImplProc and name of SpecDeclProc
     // use classname of GenImplProc and name of SpecDeclProc
     OldClassname:=GenImplProc.Name;
     OldClassname:=GenImplProc.Name;
-    p:=length(OldClassname);
-    while (p>0) and (OldClassname[p]<>'.') do dec(p);
+    p:=GetLastDotPos(OldClassname);
     if p>0 then
     if p>0 then
       NewImplProcName:=LeftStr(OldClassname,p)+SpecDeclProc.Name
       NewImplProcName:=LeftStr(OldClassname,p)+SpecDeclProc.Name
     else
     else
@@ -17666,17 +17775,17 @@ var
   GenResultEl, NewResultEl: TPasResultElement;
   GenResultEl, NewResultEl: TPasResultElement;
   NewClass: TPTreeElement;
   NewClass: TPTreeElement;
   i: Integer;
   i: Integer;
-  GenScope: TPasGenericScope;
+  SpecScope: TPasGenericScope;
 begin
 begin
   if GenEl.GenericTemplateTypes<>nil then
   if GenEl.GenericTemplateTypes<>nil then
     begin
     begin
-    GenScope:=TPasGenericScope(PushScope(SpecEl,ScopeClass_ProcType));
+    SpecScope:=TPasGenericScope(PushScope(SpecEl,ScopeClass_ProcType));
     if SpecializedItem<>nil then
     if SpecializedItem<>nil then
       begin
       begin
       // specialized procedure type
       // specialized procedure type
-      GenScope.SpecializedFromItem:=SpecializedItem;
+      SpecScope.SpecializedFromItem:=SpecializedItem;
       AddSpecializedTemplateIdentifiers(GenEl.GenericTemplateTypes,
       AddSpecializedTemplateIdentifiers(GenEl.GenericTemplateTypes,
-        SpecializedItem,GenScope,true);
+        SpecializedItem,SpecScope,true);
       end
       end
     else
     else
       begin
       begin
@@ -18148,19 +18257,19 @@ end;
 procedure TPasResolver.SpecializeArrayType(GenEl, SpecEl: TPasArrayType;
 procedure TPasResolver.SpecializeArrayType(GenEl, SpecEl: TPasArrayType;
   SpecializedItem: TPRSpecializedTypeItem);
   SpecializedItem: TPRSpecializedTypeItem);
 var
 var
-  GenScope: TPasGenericScope;
+  SpecScope: TPasGenericScope;
 begin
 begin
   SpecEl.IndexRange:=GenEl.IndexRange;
   SpecEl.IndexRange:=GenEl.IndexRange;
   SpecEl.PackMode:=GenEl.PackMode;
   SpecEl.PackMode:=GenEl.PackMode;
   if GenEl.GenericTemplateTypes<>nil then
   if GenEl.GenericTemplateTypes<>nil then
     begin
     begin
-    GenScope:=TPasGenericScope(PushScope(SpecEl,ScopeClass_Array));
+    SpecScope:=TPasGenericScope(PushScope(SpecEl,ScopeClass_Array));
     if SpecializedItem<>nil then
     if SpecializedItem<>nil then
       begin
       begin
       // specialized generic array
       // specialized generic array
-      GenScope.SpecializedFromItem:=SpecializedItem;
+      SpecScope.SpecializedFromItem:=SpecializedItem;
       AddSpecializedTemplateIdentifiers(GenEl.GenericTemplateTypes,
       AddSpecializedTemplateIdentifiers(GenEl.GenericTemplateTypes,
-                                        SpecializedItem,GenScope,true);
+                                        SpecializedItem,SpecScope,true);
       end
       end
     else
     else
       begin
       begin
@@ -25384,12 +25493,14 @@ function TPasResolver.GetTypeDescription(aType: TPasType; AddPath: boolean): str
       begin
       begin
       i:=GetTypeParameterCount(TPasGenericType(aType));
       i:=GetTypeParameterCount(TPasGenericType(aType));
       if i>0 then
       if i>0 then
+        // generic, not specialized
         Result:=Result+GetGenericParamCommas(GetTypeParameterCount(TPasGenericType(aType)))
         Result:=Result+GetGenericParamCommas(GetTypeParameterCount(TPasGenericType(aType)))
       else if aType.CustomData is TPasGenericScope then
       else if aType.CustomData is TPasGenericScope then
         begin
         begin
         GenScope:=TPasGenericScope(aType.CustomData);
         GenScope:=TPasGenericScope(aType.CustomData);
-        if GenScope.SpecializedFromItem<>nil then
+        if (GenScope.SpecializedFromItem<>nil) and IsValidIdent(aType.Name) then
           begin
           begin
+          // specialized without params in name -> append params
           Params:=GenScope.SpecializedFromItem.Params;
           Params:=GenScope.SpecializedFromItem.Params;
           Result:=Result+'<';
           Result:=Result+'<';
           for i:=0 to length(Params)-1 do
           for i:=0 to length(Params)-1 do
@@ -29527,6 +29638,7 @@ function TPasResolver.CheckClassIsClass(SrcType, DestType: TPasType): integer;
 // check if Src is equal or descends from Dest
 // check if Src is equal or descends from Dest
 // Generics: TBird<T> is both directions a TBird<word>
 // Generics: TBird<T> is both directions a TBird<word>
 //       and TBird<TMap<T>> is both directions a TBird<TMap<word>>
 //       and TBird<TMap<T>> is both directions a TBird<TMap<word>>
+//       but a TBird<word> is not a TBird<char>
 
 
   function CheckSpecialized(SrcScope, DestScope: TPasGenericScope): boolean;
   function CheckSpecialized(SrcScope, DestScope: TPasGenericScope): boolean;
   var
   var

+ 24 - 2
packages/fcl-passrc/tests/tcresolvegenerics.pas

@@ -5,7 +5,8 @@ unit tcresolvegenerics;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, testregistry, tcresolver, PasResolveEval, PParser;
+  Classes, SysUtils, testregistry, tcresolver, PasResolveEval, PParser,
+  PScanner;
 
 
 type
 type
 
 
@@ -91,7 +92,8 @@ type
     procedure TestGen_Class_MemberTypeConstructor;
     procedure TestGen_Class_MemberTypeConstructor;
     procedure TestGen_Class_AliasMemberType;
     procedure TestGen_Class_AliasMemberType;
     procedure TestGen_Class_AccessGenericMemberTypeFail;
     procedure TestGen_Class_AccessGenericMemberTypeFail;
-    procedure TestGen_Class_ReferenceTo; // ToDo
+    procedure TestGen_Class_ReferenceTo;
+    procedure TestGen_Class_TwoSpecsAreNotRelatedWarn;
     procedure TestGen_Class_List;
     procedure TestGen_Class_List;
     // ToDo: different modeswitches at parse time and specialize time
     // ToDo: different modeswitches at parse time and specialize time
 
 
@@ -1568,6 +1570,26 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
+procedure TTestResolveGenerics.TestGen_Class_TwoSpecsAreNotRelatedWarn;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class end;',
+  '  TBird<T> = class F: T; end;',
+  '  TBirdWord = TBird<Word>;',
+  '  TBirdChar = TBird<Char>;',
+  'var',
+  '  w: TBirdWord;',
+  '  c: TBirdChar;',
+  'begin',
+  '  w:=TBirdWord(c);',
+  '']);
+  ParseProgram;
+  CheckResolverHint(mtWarning,nClassTypesAreNotRelatedXY,'Class types "TBird<System.Char>" and "TBird<System.Word>" are not related');
+end;
+
 procedure TTestResolveGenerics.TestGen_Class_List;
 procedure TTestResolveGenerics.TestGen_Class_List;
 begin
 begin
   StartProgram(false);
   StartProgram(false);

File diff suppressed because it is too large
+ 229 - 200
packages/pastojs/src/fppas2js.pp


+ 33 - 27
packages/pastojs/tests/tcgenerics.pas

@@ -81,7 +81,7 @@ type
 
 
     // generic procedure type
     // generic procedure type
     procedure TestGen_ProcType_ProcLocal;
     procedure TestGen_ProcType_ProcLocal;
-    procedure TestGen_ProcType_ProcLocal_RTTI;
+    procedure TestGen_ProcType_Local_RTTI_Fail;
     procedure TestGen_ProcType_ParamUnitImpl;
     procedure TestGen_ProcType_ParamUnitImpl;
   end;
   end;
 
 
@@ -309,9 +309,9 @@ begin
     LinesToStr([ // statements
     LinesToStr([ // statements
     'var $impl = $mod.$impl;',
     'var $impl = $mod.$impl;',
     'rtl.recNewT($mod, "TAnt$G1", function () {',
     'rtl.recNewT($mod, "TAnt$G1", function () {',
+    '  var $r = $mod.$rtti.$Record("TAnt<Test1.TBird>", {});',
     '  this.$initSpec = function () {',
     '  this.$initSpec = function () {',
     '    this.x = $impl.TBird.$new();',
     '    this.x = $impl.TBird.$new();',
-    '    var $r = $mod.$rtti.$Record("TAnt$G1", {});',
     '    $r.addField("x", $mod.$rtti["TBird"]);',
     '    $r.addField("x", $mod.$rtti["TBird"]);',
     '  };',
     '  };',
     '  this.$eq = function (b) {',
     '  this.$eq = function (b) {',
@@ -323,7 +323,7 @@ begin
     '}, true);',
     '}, true);',
     '']),
     '']),
     LinesToStr([ // $mod.$init
     LinesToStr([ // $mod.$init
-    '$impl.p = $mod.$rtti["TAnt$G1"];',
+    '$impl.p = $mod.$rtti["TAnt<Test1.TBird>"];',
     '']),
     '']),
     LinesToStr([ // statements
     LinesToStr([ // statements
     'rtl.recNewT($impl, "TBird", function () {',
     'rtl.recNewT($impl, "TBird", function () {',
@@ -598,7 +598,7 @@ begin
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestGen_Class_TypeInfo',
   CheckSource('TestGen_Class_TypeInfo',
     LinesToStr([ // statements
     LinesToStr([ // statements
-    '$mod.$rtti.$Class("TBird$G1");',
+    '$mod.$rtti.$Class("TBird<System.Word>");',
     'rtl.createClass($mod, "TObject", null, function () {',
     'rtl.createClass($mod, "TObject", null, function () {',
     '  this.$init = function () {',
     '  this.$init = function () {',
     '  };',
     '  };',
@@ -612,12 +612,12 @@ begin
     '  };',
     '  };',
     '  var $r = this.$rtti;',
     '  var $r = this.$rtti;',
     '  $r.addField("m", rtl.word);',
     '  $r.addField("m", rtl.word);',
-    '});',
+    '}, "TBird<System.Word>");',
     'this.b = null;',
     'this.b = null;',
     'this.p = null;',
     'this.p = null;',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
-    '$mod.p = $mod.$rtti["TBird$G1"];',
+    '$mod.p = $mod.$rtti["TBird<System.Word>"];',
     '$mod.p = $mod.b.$rtti;',
     '$mod.p = $mod.b.$rtti;',
     '']));
     '']));
 end;
 end;
@@ -870,7 +870,7 @@ begin
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     '$mod.w = $mod.c;',
     '$mod.w = $mod.c;',
     '']));
     '']));
-  CheckHint(mtWarning,nClassTypesAreNotRelatedXY,'Class types "TBird$G2<Char>" and "TBird$G1<Word>" are not related');
+  CheckHint(mtWarning,nClassTypesAreNotRelatedXY,'Class types "TBird<System.Char>" and "TBird<System.Word>" are not related');
   CheckResolverUnexpectedHints();
   CheckResolverUnexpectedHints();
 end;
 end;
 
 
@@ -1071,8 +1071,8 @@ begin
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestGen_ClassForward_CircleRTTI',
   CheckSource('TestGen_ClassForward_CircleRTTI',
     LinesToStr([ // statements
     LinesToStr([ // statements
-    '$mod.$rtti.$Class("TAnt$G2");',
-    '$mod.$rtti.$Class("TFish$G2");',
+    '$mod.$rtti.$Class("TAnt<System.Word>");',
+    '$mod.$rtti.$Class("TFish<System.Word>");',
     'rtl.createClass($mod, "TObject", null, function () {',
     'rtl.createClass($mod, "TObject", null, function () {',
     '  this.$init = function () {',
     '  this.$init = function () {',
     '  };',
     '  };',
@@ -1091,8 +1091,8 @@ begin
     '    $mod.TPersistent.$final.call(this);',
     '    $mod.TPersistent.$final.call(this);',
     '  };',
     '  };',
     '  var $r = this.$rtti;',
     '  var $r = this.$rtti;',
-    '  $r.addField("f", $mod.$rtti["TFish$G2"]);',
-    '});',
+    '  $r.addField("f", $mod.$rtti["TFish<System.Word>"]);',
+    '}, "TAnt<System.Word>");',
     'rtl.createClass($mod, "TFish$G2", $mod.TPersistent, function () {',
     'rtl.createClass($mod, "TFish$G2", $mod.TPersistent, function () {',
     '  this.$init = function () {',
     '  this.$init = function () {',
     '    $mod.TPersistent.$init.call(this);',
     '    $mod.TPersistent.$init.call(this);',
@@ -1103,14 +1103,14 @@ begin
     '    $mod.TPersistent.$final.call(this);',
     '    $mod.TPersistent.$final.call(this);',
     '  };',
     '  };',
     '  var $r = this.$rtti;',
     '  var $r = this.$rtti;',
-    '  $r.addField("a", $mod.$rtti["TAnt$G2"]);',
-    '});',
+    '  $r.addField("a", $mod.$rtti["TAnt<System.Word>"]);',
+    '}, "TFish<System.Word>");',
     'this.WordFish = null;',
     'this.WordFish = null;',
     'this.p = null;',
     'this.p = null;',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
-    '$mod.p = $mod.$rtti["TAnt$G2"];',
-    '$mod.p = $mod.$rtti["TFish$G2"];',
+    '$mod.p = $mod.$rtti["TAnt<System.Word>"];',
+    '$mod.p = $mod.$rtti["TFish<System.Word>"];',
     '']));
     '']));
 end;
 end;
 
 
@@ -1314,11 +1314,11 @@ begin
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestGen_ExtClass_RTTI',
   CheckSource('TestGen_ExtClass_RTTI',
     LinesToStr([ // statements
     LinesToStr([ // statements
-    '$mod.$rtti.$ExtClass("TGJSSET$G1", {',
+    '$mod.$rtti.$ExtClass("TGJSSET<System.JSValue>", {',
     '  jsclass: "SET"',
     '  jsclass: "SET"',
     '});',
     '});',
     '$mod.$rtti.$RefToProcVar("TJSSetEventProc", {',
     '$mod.$rtti.$RefToProcVar("TJSSetEventProc", {',
-    '  procsig: rtl.newTIProcSig([["value", rtl.jsvalue], ["key", rtl.nativeint], ["set_", $mod.$rtti["TGJSSET$G1"]]])',
+    '  procsig: rtl.newTIProcSig([["value", rtl.jsvalue], ["key", rtl.nativeint], ["set_", $mod.$rtti["TGJSSET<System.JSValue>"]]])',
     '});',
     '});',
     'this.p = null;',
     'this.p = null;',
     '']),
     '']),
@@ -1360,7 +1360,7 @@ begin
     'rtl.module("UnitA", ["system"], function () {',
     'rtl.module("UnitA", ["system"], function () {',
     '  var $mod = this;',
     '  var $mod = this;',
     '  var $impl = $mod.$impl;',
     '  var $impl = $mod.$impl;',
-    '  $mod.$rtti.$ExtClass("TAnt$G1", {',
+    '  $mod.$rtti.$ExtClass("TAnt<UnitA.TBird>", {',
     '    jsclass: "SET"',
     '    jsclass: "SET"',
     '  });',
     '  });',
     '  $mod.$init = function () {',
     '  $mod.$init = function () {',
@@ -1432,7 +1432,7 @@ begin
     '  this.$final = function () {',
     '  this.$final = function () {',
     '  };',
     '  };',
     '});',
     '});',
-    'rtl.createInterface($mod, "IBird$G2", "{7D9907A1-5178-37B5-9D32-7BC020005905}", ["GetSize", "SetSize", "DoIt"], $mod.IUnknown);',
+    'rtl.createInterface($mod, "IBird$G2", "{33AB51C6-6240-3BDF-B4B0-D48A593EAB0A}", ["GetSize", "SetSize", "DoIt"], $mod.IUnknown);',
     'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
     'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
     '  rtl.addIntf(this, $mod.IBird$G2);',
     '  rtl.addIntf(this, $mod.IBird$G2);',
     '});',
     '});',
@@ -2061,28 +2061,30 @@ begin
   '  s: specialize TStatic<TBird>;',
   '  s: specialize TStatic<TBird>;',
   'begin',
   'begin',
   '  d[0].b:=s[1].b;',
   '  d[0].b:=s[1].b;',
+  '  s:=s;',
   '']));
   '']));
   Add([
   Add([
   'uses UnitA;',
   'uses UnitA;',
   'begin',
   'begin',
-  'end.']);
+  '']);
   ConvertProgram;
   ConvertProgram;
   CheckUnit('UnitA.pas',
   CheckUnit('UnitA.pas',
     LinesToStr([ // statements
     LinesToStr([ // statements
     'rtl.module("UnitA", ["system"], function () {',
     'rtl.module("UnitA", ["system"], function () {',
     '  var $mod = this;',
     '  var $mod = this;',
     '  var $impl = $mod.$impl;',
     '  var $impl = $mod.$impl;',
-    '  $mod.$rtti.$DynArray("TDyn$G1", {});',
+    '  $mod.$rtti.$DynArray("TDyn<UnitA.TBird>", {});',
     '  this.TStatic$G1$clone = function (a) {',
     '  this.TStatic$G1$clone = function (a) {',
     '    var r = [];',
     '    var r = [];',
     '    for (var i = 0; i < 2; i++) r.push($impl.TBird.$clone(a[i]));',
     '    for (var i = 0; i < 2; i++) r.push($impl.TBird.$clone(a[i]));',
     '    return r;',
     '    return r;',
     '  };',
     '  };',
-    '  $mod.$rtti.$StaticArray("TStatic$G1", {',
+    '  $mod.$rtti.$StaticArray("TStatic<UnitA.TBird>", {',
     '    dims: [2]',
     '    dims: [2]',
     '  });',
     '  });',
     '  $mod.$init = function () {',
     '  $mod.$init = function () {',
     '    $impl.d[0].b = $impl.s[0].b;',
     '    $impl.d[0].b = $impl.s[0].b;',
+    '    $impl.s = $mod.TStatic$G1$clone($impl.s);',
     '  };',
     '  };',
     '}, null, function () {',
     '}, null, function () {',
     '  var $mod = this;',
     '  var $mod = this;',
@@ -2104,8 +2106,8 @@ begin
     '});']));
     '});']));
   CheckSource('TestGen_Class_ClassVarRecord_UnitImpl',
   CheckSource('TestGen_Class_ClassVarRecord_UnitImpl',
     LinesToStr([ // statements
     LinesToStr([ // statements
-    'pas.UnitA.$rtti["TDyn$G1"].eltype = pas.UnitA.$rtti["TBird"];',
-    'pas.UnitA.$rtti["TStatic$G1"].eltype = pas.UnitA.$rtti["TBird"];',
+    'pas.UnitA.$rtti["TDyn<UnitA.TBird>"].eltype = pas.UnitA.$rtti["TBird"];',
+    'pas.UnitA.$rtti["TStatic<UnitA.TBird>"].eltype = pas.UnitA.$rtti["TBird"];',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     '']));
     '']));
@@ -2142,7 +2144,7 @@ begin
     '']));
     '']));
 end;
 end;
 
 
-procedure TTestGenerics.TestGen_ProcType_ProcLocal_RTTI;
+procedure TTestGenerics.TestGen_ProcType_Local_RTTI_Fail;
 begin
 begin
   WithTypeInfo:=true;
   WithTypeInfo:=true;
   StartProgram(false);
   StartProgram(false);
@@ -2183,8 +2185,10 @@ begin
   'var',
   'var',
   '  f: specialize TAnt<TBird>;',
   '  f: specialize TAnt<TBird>;',
   '  b: TBird;',
   '  b: TBird;',
+  '  p: pointer;',
   'begin',
   'begin',
   '  b:=f(b);',
   '  b:=f(b);',
+  '  p:=typeinfo(f);',
   '']));
   '']));
   Add([
   Add([
   'uses UnitA;',
   'uses UnitA;',
@@ -2196,13 +2200,14 @@ begin
     'rtl.module("UnitA", ["system"], function () {',
     'rtl.module("UnitA", ["system"], function () {',
     '  var $mod = this;',
     '  var $mod = this;',
     '  var $impl = $mod.$impl;',
     '  var $impl = $mod.$impl;',
-    '  $mod.$rtti.$ProcVar("TAnt$G1", {',
+    '  $mod.$rtti.$ProcVar("TAnt<UnitA.TBird>", {',
     '    init: function () {',
     '    init: function () {',
     '      this.procsig = rtl.newTIProcSig([["a", $mod.$rtti["TBird"], 2]], $mod.$rtti["TBird"]);',
     '      this.procsig = rtl.newTIProcSig([["a", $mod.$rtti["TBird"], 2]], $mod.$rtti["TBird"]);',
     '    }',
     '    }',
     '  });',
     '  });',
     '  $mod.$init = function () {',
     '  $mod.$init = function () {',
     '    $impl.b.$assign($impl.f($impl.b));',
     '    $impl.b.$assign($impl.f($impl.b));',
+    '    $impl.p = $mod.$rtti["TAnt<UnitA.TBird>"];',
     '  };',
     '  };',
     '}, null, function () {',
     '}, null, function () {',
     '  var $mod = this;',
     '  var $mod = this;',
@@ -2221,10 +2226,11 @@ begin
     '  });',
     '  });',
     '  $impl.f = null;',
     '  $impl.f = null;',
     '  $impl.b = $impl.TBird.$new();',
     '  $impl.b = $impl.TBird.$new();',
+    '  $impl.p = null;',
     '});']));
     '});']));
   CheckSource('TestGen_Class_ClassVarRecord_UnitImpl',
   CheckSource('TestGen_Class_ClassVarRecord_UnitImpl',
     LinesToStr([ // statements
     LinesToStr([ // statements
-    'pas.UnitA.$rtti["TAnt$G1"].init();',
+    'pas.UnitA.$rtti["TAnt<UnitA.TBird>"].init();',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     '']));
     '']));

+ 1 - 0
tests/Makefile

@@ -2458,6 +2458,7 @@ CPP_OBJECTS=$(addprefix $(C_OBJECTS_DIR)/, $(subst .cpp,.o, $(CPP_SOURCES)))
 TASM_OBJECTS=$(addprefix $(C_OBJECTS_DIR)/, $(subst .asm,.obj, $(TASM_SOURCES)))
 TASM_OBJECTS=$(addprefix $(C_OBJECTS_DIR)/, $(subst .asm,.obj, $(TASM_SOURCES)))
 create_c_objects:
 create_c_objects:
 ifneq ($(TEST_CCOMPILER),)
 ifneq ($(TEST_CCOMPILER),)
+		$(MKDIRTREE) $(C_OBJECTS_DIR)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(C_SOURCES)) $(C_OBJECTS_DIR)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(C_SOURCES)) $(C_OBJECTS_DIR)
 		$(MAKE) $(C_OBJECTS)
 		$(MAKE) $(C_OBJECTS)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(CPP_SOURCES)) $(C_OBJECTS_DIR)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(CPP_SOURCES)) $(C_OBJECTS_DIR)

+ 3 - 2
tests/Makefile.fpc

@@ -255,6 +255,7 @@ TASM_OBJECTS=$(addprefix $(C_OBJECTS_DIR)/, $(subst .asm,.obj, $(TASM_SOURCES)))
 
 
 create_c_objects:
 create_c_objects:
 ifneq ($(TEST_CCOMPILER),)
 ifneq ($(TEST_CCOMPILER),)
+		$(MKDIRTREE) $(C_OBJECTS_DIR)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(C_SOURCES)) $(C_OBJECTS_DIR)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(C_SOURCES)) $(C_OBJECTS_DIR)
 		$(MAKE) $(C_OBJECTS)
 		$(MAKE) $(C_OBJECTS)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(CPP_SOURCES)) $(C_OBJECTS_DIR)
 		-$(COPY) $(addprefix $(C_SOURCE_DIR)/, $(CPP_SOURCES)) $(C_OBJECTS_DIR)
@@ -278,7 +279,7 @@ $(C_OBJECTS) : %.o: %.c
 
 
 $(CPP_OBJECTS) : %.o: %.cpp
 $(CPP_OBJECTS) : %.o: %.cpp
 		$(TEST_CCOMPILER) -c $(TEST_CFLAGS) $< -o $@
 		$(TEST_CCOMPILER) -c $(TEST_CFLAGS) $< -o $@
-		
+
 copyfiles:
 copyfiles:
         -$(MKDIRTREE) $(TEST_OUTPUTDIR)/test/cg
         -$(MKDIRTREE) $(TEST_OUTPUTDIR)/test/cg
         -$(COPY) $(C_OBJECTS) $(TEST_OUTPUTDIR)/test/cg
         -$(COPY) $(C_OBJECTS) $(TEST_OUTPUTDIR)/test/cg
@@ -460,7 +461,7 @@ test_c_objects: testprep
 	$(MAKE) $(patsubst %.pp,%.elg, $(wildcard test/cg/cdecl/tcalext*.pp))
 	$(MAKE) $(patsubst %.pp,%.elg, $(wildcard test/cg/cdecl/tcalext*.pp))
 	$(MAKE) $(patsubst %.pp,%.log, $(wildcard test/cg/cdecl/tcppcl*.pp))
 	$(MAKE) $(patsubst %.pp,%.log, $(wildcard test/cg/cdecl/tcppcl*.pp))
 	$(MAKE) $(patsubst %.pp,%.elg, $(wildcard test/cg/cdecl/tcppcl*.pp))
 	$(MAKE) $(patsubst %.pp,%.elg, $(wildcard test/cg/cdecl/tcppcl*.pp))
-	
+
 ################################
 ################################
 # Compile and Run tests
 # Compile and Run tests
 #
 #

BIN
tests/test/cg/obj/freertos/xtensa-call0/cpptcl1.o


BIN
tests/test/cg/obj/freertos/xtensa-call0/cpptcl2.o


BIN
tests/test/cg/obj/freertos/xtensa-call0/ctest.o


BIN
tests/test/cg/obj/freertos/xtensa-call0/tcext3.o


BIN
tests/test/cg/obj/freertos/xtensa-call0/tcext4.o


BIN
tests/test/cg/obj/freertos/xtensa-call0/tcext5.o


BIN
tests/test/cg/obj/freertos/xtensa-call0/tcext6.o


+ 8 - 7
utils/pas2js/dist/rtl.js

@@ -286,15 +286,16 @@ var rtl = {
     return parent;
     return parent;
   },
   },
 
 
-  initClass: function(c,parent,name,initfn){
+  initClass: function(c,parent,name,initfn,rttiname){
+    if (!rttiname) rttiname = name;
     parent[name] = c;
     parent[name] = c;
     c.$class = c; // Note: o.$class === Object.getPrototypeOf(o)
     c.$class = c; // Note: o.$class === Object.getPrototypeOf(o)
-    c.$classname = name;
+    c.$classname = rttiname;
     parent = rtl.initStruct(c,parent,name);
     parent = rtl.initStruct(c,parent,name);
     c.$fullname = parent.$name+'.'+name;
     c.$fullname = parent.$name+'.'+name;
     // rtti
     // rtti
     if (rtl.debug_rtti) rtl.debug('initClass '+c.$fullname);
     if (rtl.debug_rtti) rtl.debug('initClass '+c.$fullname);
-    var t = c.$module.$rtti.$Class(c.$name,{ "class": c });
+    var t = c.$module.$rtti.$Class(rttiname,{ "class": c });
     c.$rtti = t;
     c.$rtti = t;
     if (rtl.isObject(c.$ancestor)) t.ancestor = c.$ancestor.$rtti;
     if (rtl.isObject(c.$ancestor)) t.ancestor = c.$ancestor.$rtti;
     if (!t.ancestor) t.ancestor = null;
     if (!t.ancestor) t.ancestor = null;
@@ -302,7 +303,7 @@ var rtl = {
     initfn.call(c);
     initfn.call(c);
   },
   },
 
 
-  createClass: function(parent,name,ancestor,initfn){
+  createClass: function(parent,name,ancestor,initfn,rttiname){
     // create a normal class,
     // create a normal class,
     // ancestor must be null or a normal class,
     // ancestor must be null or a normal class,
     // the root ancestor can be an external class
     // the root ancestor can be an external class
@@ -340,10 +341,10 @@ var rtl = {
         this.$final();
         this.$final();
       };
       };
     };
     };
-    rtl.initClass(c,parent,name,initfn);
+    rtl.initClass(c,parent,name,initfn,rttiname);
   },
   },
 
 
-  createClassExt: function(parent,name,ancestor,newinstancefnname,initfn){
+  createClassExt: function(parent,name,ancestor,newinstancefnname,initfn,rttiname){
     // Create a class using an external ancestor.
     // Create a class using an external ancestor.
     // If newinstancefnname is given, use that function to create the new object.
     // If newinstancefnname is given, use that function to create the new object.
     // If exist call BeforeDestruction and AfterConstruction.
     // If exist call BeforeDestruction and AfterConstruction.
@@ -391,7 +392,7 @@ var rtl = {
       if (this[fnname]) this[fnname]();
       if (this[fnname]) this[fnname]();
       if (this.$final) this.$final();
       if (this.$final) this.$final();
     };
     };
-    rtl.initClass(c,parent,name,initfn);
+    rtl.initClass(c,parent,name,initfn,rttiname);
     if (isFunc){
     if (isFunc){
       function f(){}
       function f(){}
       f.prototype = c;
       f.prototype = c;

Some files were not shown because too many files changed in this diff