浏览代码

--- Merging r39785 into '.':
U packages/fcl-stl/src/gset.pp
--- Recording mergeinfo for merge of r39785 into '.':
U .
--- Merging r39786 into '.':
A tests/tbs/tb0651.pp
U compiler/symdef.pas
--- Recording mergeinfo for merge of r39786 into '.':
G .
--- Merging r39787 into '.':
U compiler/pexpr.pas
A tests/webtbs/uw34287a.pp
A tests/webtbs/tw34287.pp
A tests/webtbs/uw34287b.pp
--- Recording mergeinfo for merge of r39787 into '.':
G .
--- Merging r39788 into '.':
U compiler/nbas.pas
--- Recording mergeinfo for merge of r39788 into '.':
G .
--- Merging r39812 into '.':
G compiler/pexpr.pas
--- Recording mergeinfo for merge of r39812 into '.':
G .

# revisions: 39785,39786,39787,39788,39812

git-svn-id: branches/fixes_3_2@39835 -

marco 6 年之前
父节点
当前提交
338873d7a7
共有 9 个文件被更改,包括 290 次插入62 次删除
  1. 4 0
      .gitattributes
  2. 8 0
      compiler/nbas.pas
  3. 119 58
      compiler/pexpr.pas
  4. 6 2
      compiler/symdef.pas
  5. 2 2
      packages/fcl-stl/src/gset.pp
  6. 55 0
      tests/tbs/tb0651.pp
  7. 22 0
      tests/webtbs/tw34287.pp
  8. 37 0
      tests/webtbs/uw34287a.pp
  9. 37 0
      tests/webtbs/uw34287b.pp

+ 4 - 0
.gitattributes

@@ -11597,6 +11597,7 @@ tests/tbs/tb0646b.pp svneol=native#text/pascal
 tests/tbs/tb0648.pp svneol=native#text/pascal
 tests/tbs/tb0648.pp svneol=native#text/pascal
 tests/tbs/tb0649.pp -text svneol=native#text/pascal
 tests/tbs/tb0649.pp -text svneol=native#text/pascal
 tests/tbs/tb0650.pp svneol=native#text/pascal
 tests/tbs/tb0650.pp svneol=native#text/pascal
+tests/tbs/tb0651.pp svneol=native#text/pascal
 tests/tbs/tb205.pp svneol=native#text/plain
 tests/tbs/tb205.pp svneol=native#text/plain
 tests/tbs/tb610.pp svneol=native#text/pascal
 tests/tbs/tb610.pp svneol=native#text/pascal
 tests/tbs/tb613.pp svneol=native#text/plain
 tests/tbs/tb613.pp svneol=native#text/plain
@@ -16248,6 +16249,7 @@ tests/webtbs/tw34124.pp svneol=native#text/pascal
 tests/webtbs/tw3418.pp svneol=native#text/plain
 tests/webtbs/tw3418.pp svneol=native#text/plain
 tests/webtbs/tw3423.pp svneol=native#text/plain
 tests/webtbs/tw3423.pp svneol=native#text/plain
 tests/webtbs/tw34239.pp svneol=native#text/pascal
 tests/webtbs/tw34239.pp svneol=native#text/pascal
+tests/webtbs/tw34287.pp svneol=native#text/pascal
 tests/webtbs/tw3429.pp svneol=native#text/plain
 tests/webtbs/tw3429.pp svneol=native#text/plain
 tests/webtbs/tw3433.pp svneol=native#text/plain
 tests/webtbs/tw3433.pp svneol=native#text/plain
 tests/webtbs/tw3435.pp svneol=native#text/plain
 tests/webtbs/tw3435.pp svneol=native#text/plain
@@ -16858,6 +16860,8 @@ tests/webtbs/uw3340.pp svneol=native#text/plain
 tests/webtbs/uw3353.pp svneol=native#text/plain
 tests/webtbs/uw3353.pp svneol=native#text/plain
 tests/webtbs/uw3356.pp svneol=native#text/plain
 tests/webtbs/uw3356.pp svneol=native#text/plain
 tests/webtbs/uw33839.pp -text svneol=native#text/pascal
 tests/webtbs/uw33839.pp -text svneol=native#text/pascal
+tests/webtbs/uw34287a.pp svneol=native#text/pascal
+tests/webtbs/uw34287b.pp svneol=native#text/pascal
 tests/webtbs/uw3429.pp svneol=native#text/plain
 tests/webtbs/uw3429.pp svneol=native#text/plain
 tests/webtbs/uw3474a.pp svneol=native#text/plain
 tests/webtbs/uw3474a.pp svneol=native#text/plain
 tests/webtbs/uw3474b.pp svneol=native#text/plain
 tests/webtbs/uw3474b.pp svneol=native#text/plain

+ 8 - 0
compiler/nbas.pas

@@ -51,7 +51,9 @@ interface
        tspecializenode = class(tunarynode)
        tspecializenode = class(tunarynode)
           sym:tsym;
           sym:tsym;
           getaddr:boolean;
           getaddr:boolean;
+          inheriteddef:tdef;
           constructor create(l:tnode;g:boolean;s:tsym);virtual;
           constructor create(l:tnode;g:boolean;s:tsym);virtual;
+          constructor create_inherited(l:tnode;g:boolean;s:tsym;i:tdef);virtual;
           function pass_1:tnode;override;
           function pass_1:tnode;override;
           function pass_typecheck:tnode;override;
           function pass_typecheck:tnode;override;
        end;
        end;
@@ -430,6 +432,12 @@ implementation
          getaddr:=g;
          getaddr:=g;
       end;
       end;
 
 
+    constructor tspecializenode.create_inherited(l:tnode;g:boolean;s:tsym;i:tdef);
+      begin
+        create(l,g,s);
+        inheriteddef:=i;
+      end;
+
 
 
     function tspecializenode.pass_typecheck:tnode;
     function tspecializenode.pass_typecheck:tnode;
       begin
       begin

+ 119 - 58
compiler/pexpr.pas

@@ -1005,7 +1005,7 @@ implementation
           end;
           end;
 
 
          { only need to get the address of the procedure? Check token because
          { only need to get the address of the procedure? Check token because
-           in the case of opening parenthesis is possible to get pointer to 
+           in the case of opening parenthesis is possible to get pointer to
            function result (lack of checking for token was the reason of
            function result (lack of checking for token was the reason of
            tw10933.pp test failure) }
            tw10933.pp test failure) }
          if getaddr and (token<>_LKLAMMER) then
          if getaddr and (token<>_LKLAMMER) then
@@ -3362,6 +3362,9 @@ implementation
          filepos    : tfileposinfo;
          filepos    : tfileposinfo;
          callflags  : tcallnodeflags;
          callflags  : tcallnodeflags;
          idstr      : tidstring;
          idstr      : tidstring;
+         spezcontext : tspecializationcontext;
+         isspecialize,
+         mightbegeneric,
          useself,
          useself,
          dopostfix,
          dopostfix,
          again,
          again,
@@ -3376,6 +3379,7 @@ implementation
         filepos:=current_tokenpos;
         filepos:=current_tokenpos;
         again:=false;
         again:=false;
         pd:=nil;
         pd:=nil;
+        isspecialize:=false;
         if token=_ID then
         if token=_ID then
          begin
          begin
            again:=true;
            again:=true;
@@ -3483,6 +3487,7 @@ implementation
                       hclassdef:=java_fpcbaserecordtype
                       hclassdef:=java_fpcbaserecordtype
                     else
                     else
                       internalerror(2012012401);
                       internalerror(2012012401);
+                    spezcontext:=nil;
                     { if inherited; only then we need the method with
                     { if inherited; only then we need the method with
                       the same name }
                       the same name }
                     if token <> _ID then
                     if token <> _ID then
@@ -3508,6 +3513,18 @@ implementation
                      end
                      end
                     else
                     else
                      begin
                      begin
+                       if not (m_delphi in current_settings.modeswitches) and
+                           (block_type in inline_specialization_block_types) and
+                           (token=_ID) and
+                           (idtoken=_SPECIALIZE) then
+                         begin
+                           consume(_ID);
+                           if token<>_ID then
+                             message(parser_e_methode_id_expected);
+                           isspecialize:=true;
+                         end
+                       else
+                         isspecialize:=false;
                        hs:=pattern;
                        hs:=pattern;
                        hsorg:=orgpattern;
                        hsorg:=orgpattern;
                        consume(_ID);
                        consume(_ID);
@@ -3517,53 +3534,71 @@ implementation
                          searchsym_in_helper(tobjectdef(current_structdef),tobjectdef(current_structdef),hs,srsym,srsymtable,[ssf_has_inherited])
                          searchsym_in_helper(tobjectdef(current_structdef),tobjectdef(current_structdef),hs,srsym,srsymtable,[ssf_has_inherited])
                        else
                        else
                          searchsym_in_class(hclassdef,current_structdef,hs,srsym,srsymtable,[ssf_search_helper]);
                          searchsym_in_class(hclassdef,current_structdef,hs,srsym,srsymtable,[ssf_search_helper]);
+                       if isspecialize and assigned(srsym) then
+                         begin
+                           if not handle_specialize_inline_specialization(srsym,srsymtable,spezcontext) then
+                             srsym:=nil;
+                         end;
                      end;
                      end;
                     if assigned(srsym) then
                     if assigned(srsym) then
                      begin
                      begin
-                       check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+                       mightbegeneric:=(m_delphi in current_settings.modeswitches) and
+                                         (token in [_LT,_LSHARPBRACKET]) and
+                                         (sp_generic_dummy in srsym.symoptions);
                        { load the procdef from the inherited class and
                        { load the procdef from the inherited class and
                          not from self }
                          not from self }
                        case srsym.typ of
                        case srsym.typ of
+                         typesym,
                          procsym:
                          procsym:
                            begin
                            begin
-                             useself:=false;
-                             if is_objectpascal_helper(current_structdef) then
-                               begin
-                                 { for a helper load the procdef either from the
-                                   extended type, from the parent helper or from
-                                   the extended type of the parent helper
-                                   depending on the def the found symbol belongs
-                                   to }
-                                 if (srsym.Owner.defowner.typ=objectdef) and
-                                     is_objectpascal_helper(tobjectdef(srsym.Owner.defowner)) then
-                                   if def_is_related(current_structdef,tdef(srsym.Owner.defowner)) and
-                                       assigned(tobjectdef(current_structdef).childof) then
-                                     hdef:=tobjectdef(current_structdef).childof
-                                   else
-                                     begin
-                                       hdef:=tobjectdef(srsym.Owner.defowner).extendeddef;
-                                       useself:=true;
-                                     end
-                                 else
-                                   begin
-                                     hdef:=tdef(srsym.Owner.defowner);
-                                     useself:=true;
-                                   end;
-                               end
-                             else
-                               hdef:=hclassdef;
-                             if (po_classmethod in current_procinfo.procdef.procoptions) or
-                                (po_staticmethod in current_procinfo.procdef.procoptions) then
-                               hdef:=cclassrefdef.create(hdef);
-                             if useself then
+                             { typesym is only a valid choice if we're dealing
+                               with a potential generic }
+                             if (srsym.typ=typesym) and not mightbegeneric then
                                begin
                                begin
-                                 p1:=ctypeconvnode.create_internal(load_self_node,hdef);
+                                 Message(parser_e_methode_id_expected);
+                                 p1:=cerrornode.create;
                                end
                                end
                              else
                              else
                                begin
                                begin
-                                 p1:=ctypenode.create(hdef);
-                                 { we need to allow helpers here }
-                                 ttypenode(p1).helperallowed:=true;
+                                 useself:=false;
+                                 if is_objectpascal_helper(current_structdef) then
+                                   begin
+                                     { for a helper load the procdef either from the
+                                       extended type, from the parent helper or from
+                                       the extended type of the parent helper
+                                       depending on the def the found symbol belongs
+                                       to }
+                                     if (srsym.Owner.defowner.typ=objectdef) and
+                                         is_objectpascal_helper(tobjectdef(srsym.Owner.defowner)) then
+                                       if def_is_related(current_structdef,tdef(srsym.Owner.defowner)) and
+                                           assigned(tobjectdef(current_structdef).childof) then
+                                         hdef:=tobjectdef(current_structdef).childof
+                                       else
+                                         begin
+                                           hdef:=tobjectdef(srsym.Owner.defowner).extendeddef;
+                                           useself:=true;
+                                         end
+                                     else
+                                       begin
+                                         hdef:=tdef(srsym.Owner.defowner);
+                                         useself:=true;
+                                       end;
+                                   end
+                                 else
+                                   hdef:=hclassdef;
+                                 if (po_classmethod in current_procinfo.procdef.procoptions) or
+                                    (po_staticmethod in current_procinfo.procdef.procoptions) then
+                                   hdef:=cclassrefdef.create(hdef);
+                                 if useself then
+                                   begin
+                                     p1:=ctypeconvnode.create_internal(load_self_node,hdef);
+                                   end
+                                 else
+                                   begin
+                                     p1:=ctypenode.create(hdef);
+                                     { we need to allow helpers here }
+                                     ttypenode(p1).helperallowed:=true;
+                                   end;
                                end;
                                end;
                            end;
                            end;
                          propertysym:
                          propertysym:
@@ -3574,11 +3609,22 @@ implementation
                              p1:=cerrornode.create;
                              p1:=cerrornode.create;
                            end;
                            end;
                        end;
                        end;
-                       callflags:=[cnf_inherited];
-                       include(current_procinfo.flags,pi_has_inherited);
-                       if anon_inherited then
-                         include(callflags,cnf_anon_inherited);
-                       do_member_read(hclassdef,getaddr,srsym,p1,again,callflags,nil);
+                       if mightbegeneric then
+                         begin
+                           p1:=cspecializenode.create_inherited(p1,getaddr,srsym,hclassdef);
+                         end
+                       else
+                         begin
+                           if not isspecialize then
+                             check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+                           callflags:=[cnf_inherited];
+                           include(current_procinfo.flags,pi_has_inherited);
+                           if anon_inherited then
+                             include(callflags,cnf_anon_inherited);
+                           do_member_read(hclassdef,getaddr,srsym,p1,again,callflags,spezcontext);
+                         end;
+                       if p1.nodetype=errorn then
+                         spezcontext.free;
                      end
                      end
                     else
                     else
                      begin
                      begin
@@ -3622,7 +3668,8 @@ implementation
                      again:=false;
                      again:=false;
                      p1:=cerrornode.create;
                      p1:=cerrornode.create;
                    end;
                    end;
-                 postfixoperators(p1,again,getaddr);
+                 if p1.nodetype<>specializen then
+                   postfixoperators(p1,again,getaddr);
                end;
                end;
 
 
              _INTCONST :
              _INTCONST :
@@ -4045,18 +4092,22 @@ implementation
           getaddr : boolean;
           getaddr : boolean;
           pload : tnode;
           pload : tnode;
           spezcontext : tspecializationcontext;
           spezcontext : tspecializationcontext;
-          structdef : tabstractrecorddef;
+          structdef,
+          inheriteddef : tabstractrecorddef;
+          callflags : tcallnodeflags;
         begin
         begin
           if n.nodetype=specializen then
           if n.nodetype=specializen then
             begin
             begin
               getaddr:=tspecializenode(n).getaddr;
               getaddr:=tspecializenode(n).getaddr;
               pload:=tspecializenode(n).left;
               pload:=tspecializenode(n).left;
+              inheriteddef:=tabstractrecorddef(tspecializenode(n).inheriteddef);
               tspecializenode(n).left:=nil;
               tspecializenode(n).left:=nil;
             end
             end
           else
           else
             begin
             begin
               getaddr:=false;
               getaddr:=false;
               pload:=nil;
               pload:=nil;
+              inheriteddef:=nil;
             end;
             end;
 
 
           if assigned(parseddef) and assigned(gensym) and assigned(p2) then
           if assigned(parseddef) and assigned(gensym) and assigned(p2) then
@@ -4104,21 +4155,31 @@ implementation
             begin
             begin
               result:=pload;
               result:=pload;
               typecheckpass(result);
               typecheckpass(result);
-              structdef:=nil;
-              case result.resultdef.typ of
-                objectdef,
-                recorddef:
-                  begin
-                    structdef:=tabstractrecorddef(result.resultdef);
-                  end;
-                classrefdef:
-                  begin
-                    structdef:=tabstractrecorddef(tclassrefdef(result.resultdef).pointeddef);
-                  end;
-                else
-                  internalerror(2015092703);
-              end;
-              do_member_read(structdef,getaddr,gensym,result,again,[],spezcontext);
+              structdef:=inheriteddef;
+              if not assigned(structdef) then
+                case result.resultdef.typ of
+                  objectdef,
+                  recorddef:
+                    begin
+                      structdef:=tabstractrecorddef(result.resultdef);
+                    end;
+                  classrefdef:
+                    begin
+                      structdef:=tabstractrecorddef(tclassrefdef(result.resultdef).pointeddef);
+                    end;
+                  else
+                    internalerror(2015092703);
+                end;
+              if not (structdef.typ in [recorddef,objectdef]) then
+                internalerror(2018092101);
+              if assigned(inheriteddef) then
+                begin
+                  callflags:=[cnf_inherited];
+                  include(current_procinfo.flags,pi_has_inherited);
+                end
+              else
+                callflags:=[];
+              do_member_read(structdef,getaddr,gensym,result,again,callflags,spezcontext);
               spezcontext:=nil;
               spezcontext:=nil;
             end
             end
           else
           else

+ 6 - 2
compiler/symdef.pas

@@ -2913,8 +2913,12 @@ implementation
              (high > (system.high(int64) div 2)))) then
              (high > (system.high(int64) div 2)))) then
 {$endif cpu64bitalu}
 {$endif cpu64bitalu}
           result := 64
           result := 64
-        else if (low >= 0) and
-           (high <= 1) then
+        else if (
+            (low >= 0) and
+            (high <= 1)
+           ) or (
+             ordtype in [pasbool8,pasbool16,pasbool32,pasbool64,bool8bit,bool16bit,bool32bit,bool64bit]
+           ) then
           result := 1
           result := 1
         else
         else
           begin
           begin

+ 2 - 2
packages/fcl-stl/src/gset.pp

@@ -53,7 +53,7 @@ type
     function RotateLeft(nod:PNode):PNode;inline;
     function RotateLeft(nod:PNode):PNode;inline;
     procedure FlipColors(nod:PNode);inline;
     procedure FlipColors(nod:PNode);inline;
     function IsRed(nod:PNode):boolean;inline;
     function IsRed(nod:PNode):boolean;inline;
-    function Insert(value:T; nod:PNode; var position:PNode):PNode;
+    function Insert(value:T; nod:PNode; out position:PNode):PNode;
     function FixUp(nod:PNode):PNode;inline;
     function FixUp(nod:PNode):PNode;inline;
     function MoveRedLeft(nod:PNode):PNode;inline;
     function MoveRedLeft(nod:PNode):PNode;inline;
     function MoveRedRight(nod:PNode):PNode;inline;
     function MoveRedRight(nod:PNode):PNode;inline;
@@ -413,7 +413,7 @@ begin
   InsertAndGetIterator := ret;
   InsertAndGetIterator := ret;
 end;
 end;
 
 
-function TSet.Insert(value:T; nod:PNode; var position:PNode):PNode;
+function TSet.Insert(value:T; nod:PNode; out position:PNode):PNode;
 begin
 begin
   if(nod=nil) then begin
   if(nod=nil) then begin
     nod:=CreateNode(value);
     nod:=CreateNode(value);

+ 55 - 0
tests/tbs/tb0651.pp

@@ -0,0 +1,55 @@
+program tb0651;
+
+{$mode objfpc}{$H+}
+
+type
+  TBooleanArray = array[0..7] of Boolean;
+
+  TBooleanByte = bitpacked array[0..7] of Boolean;
+  TBoolean16Byte = bitpacked array[0..7] of Boolean16;
+  TBoolean32Byte = bitpacked array[0..7] of Boolean32;
+  TBoolean64Byte = bitpacked array[0..7] of Boolean64;
+  TByteBoolByte = bitpacked array[0..7] of ByteBool;
+  TWordBoolByte = bitpacked array[0..7] of WordBool;
+  TLongBoolByte = bitpacked array[0..7] of LongBool;
+  TQWordBoolByte = bitpacked array[0..7] of QWordBool;
+
+generic procedure CheckValue<T>(aArr: T; const aExpected: TBooleanArray; aCode: LongInt);
+var
+  i: LongInt;
+begin
+  if SizeOf(T) <> 1 then
+    Halt(aCode * 10 + 1);
+  if BitSizeOf(T) <> 8 then
+    Halt(aCode * 10 + 2);
+  for i := 0 to High(aArr) do
+    if aArr[i] <> aExpected[i] then
+      Halt(aCode * 10 + 3 + i);
+end;
+
+var
+  exp: TBooleanArray = (True, False, True, False, False, True, False, True);
+  b: Byte = $A5;
+  pb8: TBooleanByte absolute b;
+  pb16: TBoolean16Byte absolute b;
+  pb32: TBoolean32Byte absolute b;
+  pb64: TBoolean64Byte absolute b;
+  bb8: TByteBoolByte absolute b;
+  bb16: TWordBoolByte absolute b;
+  bb32: TLongBoolByte absolute b;
+  bb64: TQWordBoolByte absolute b;
+begin
+  specialize CheckValue<TBooleanByte>(pb8, exp, 0);
+  specialize CheckValue<TBoolean16Byte>(pb16, exp, 1);
+  specialize CheckValue<TBoolean32Byte>(pb32, exp, 2);
+{$ifdef CPU64}
+  specialize CheckValue<TBoolean64Byte>(pb64, exp, 3);
+{$endif}
+  specialize CheckValue<TByteBoolByte>(bb8, exp, 4);
+  specialize CheckValue<TWordBoolByte>(bb16, exp, 5);
+  specialize CheckValue<TLongBoolByte>(bb32, exp, 6);
+{$ifdef CPU64}
+  specialize CheckValue<TQWordBoolByte>(bb64, exp, 7);
+{$endif}
+  Writeln('ok');
+end.

+ 22 - 0
tests/webtbs/tw34287.pp

@@ -0,0 +1,22 @@
+{ %NORUN }
+
+program tw34287;
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+
+uses
+  Classes,
+  uw34287a,
+  uw34287b;
+
+var
+  fooa: uw34287a.TFoo;
+  foob: uw34287b.TFoo;
+begin
+  fooa := uw34287a.TFoo.Create(nil);
+  fooa.Bar('');
+  foob := uw34287b.TFoo.Create(nil);
+  foob.Bar('');
+end.

+ 37 - 0
tests/webtbs/uw34287a.pp

@@ -0,0 +1,37 @@
+unit uw34287a;
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+
+interface
+
+uses
+  Classes;
+
+type
+  TBase = class(TComponent)
+  public
+    function Bar<T: TComponent>(const P1: string; out P2: T): Boolean;
+  end;
+
+  TFoo = class(TBase)
+  public
+    function Bar(const P1: string): Boolean;
+  end;
+
+implementation
+
+function TBase.Bar<T>(const P1: string; out P2: T): Boolean;
+begin
+  Result := False;
+end;
+
+function TFoo.Bar(const P1: string): Boolean;
+var
+  C: TComponent;
+begin
+  Result := inherited Bar<TComponent>(P1, C);
+end;
+
+end.

+ 37 - 0
tests/webtbs/uw34287b.pp

@@ -0,0 +1,37 @@
+unit uw34287b;
+
+{$IFDEF FPC}
+ {$MODE OBJFPC}{$H+}
+{$ENDIF}
+
+interface
+
+uses
+  Classes;
+
+type
+  TBase = class(TComponent)
+  public
+    generic function Bar<T: TComponent>(const P1: string; out P2: T): Boolean;
+  end;
+
+  TFoo = class(TBase)
+  public
+    function Bar(const P1: string): Boolean;
+  end;
+
+implementation
+
+generic function TBase.Bar<T>(const P1: string; out P2: T): Boolean;
+begin
+  Result := False;
+end;
+
+function TFoo.Bar(const P1: string): Boolean;
+var
+  C: TComponent;
+begin
+  Result := inherited specialize Bar<TComponent>(P1, C);
+end;
+
+end.