ソースを参照

Revert r31262. Not doing type checking on generics leads to strange warnings (e.g. because variables are not considered as written). I better deal with the compile time errors one at a time than the warnings.
The added test shows such a bogus warning (sadly the test suite can handle the occurence or absense of certain messages yet :/ )

git-svn-id: trunk@33324 -

svenbarth 9 年 前
コミット
35f8d5427f
4 ファイル変更81 行追加50 行削除
  1. 1 0
      .gitattributes
  2. 42 47
      compiler/pstatmnt.pas
  3. 1 3
      compiler/psub.pas
  4. 37 0
      tests/tbs/tb0617.pp

+ 1 - 0
.gitattributes

@@ -10874,6 +10874,7 @@ tests/tbs/tb0613.pp svneol=native#text/pascal
 tests/tbs/tb0614.pp svneol=native#text/pascal
 tests/tbs/tb0615.pp svneol=native#text/pascal
 tests/tbs/tb0616.pp svneol=native#text/pascal
+tests/tbs/tb0617.pp svneol=native#text/pascal
 tests/tbs/tb205.pp svneol=native#text/plain
 tests/tbs/tb610.pp svneol=native#text/pascal
 tests/tbs/tb613.pp svneol=native#text/plain

+ 42 - 47
compiler/pstatmnt.pas

@@ -1287,59 +1287,54 @@ implementation
              if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
                maybe_call_procvar(p,false);
 
-             { additional checks make no sense in a generic definition }
-             if not(df_generic in current_procinfo.procdef.defoptions) then
+             { blockn support because a read/write is changed into a blocknode
+               with a separate statement for each read/write operation (JM)
+               the same is true for val() if the third parameter is not 32 bit
+
+               goto nodes are created by the compiler for non local exit statements, so
+               include them as well
+             }
+             if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
+                                   continuen,labeln,blockn,exitn,goton]) or
+                ((p.nodetype=inlinen) and
+                 not is_void(p.resultdef)) or
+                ((p.nodetype=calln) and
+                 (assigned(tcallnode(p).procdefinition)) and
+                 (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
+               Message(parser_e_illegal_expression);
+
+             if not assigned(p.resultdef) then
+               do_typecheckpass(p);
+
+             { Specify that we don't use the value returned by the call.
+               This is used for :
+                - dispose of temp stack space
+                - dispose on FPU stack
+                - extended syntax checking }
+             if (p.nodetype=calln) then
                begin
-                 { blockn support because a read/write is changed into a blocknode
-                   with a separate statement for each read/write operation (JM)
-                   the same is true for val() if the third parameter is not 32 bit
-
-                   goto nodes are created by the compiler for non local exit statements, so
-                   include them as well
-                 }
-                 if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
-                                       continuen,labeln,blockn,exitn,goton]) or
-                    ((p.nodetype=inlinen) and
-                     not is_void(p.resultdef)) or
-                    ((p.nodetype=calln) and
-                     (assigned(tcallnode(p).procdefinition)) and
-                     (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
+                 exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
+
+                 { in $x- state, the function result must not be ignored }
+                 if not(cs_extsyntax in current_settings.moduleswitches) and
+                    not(is_void(p.resultdef)) and
+                    { can be nil in case there was an error in the expression }
+                    assigned(tcallnode(p).procdefinition) and
+                    { allow constructor calls to drop the result if they are
+                      called as instance methods instead of class methods }
+                    not(
+                      (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
+                      is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and
+                      assigned(tcallnode(p).methodpointer) and
+                      (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef)
+                    ) then
                    Message(parser_e_illegal_expression);
-
-                 if not assigned(p.resultdef) then
-                   do_typecheckpass(p);
-
-                 { Specify that we don't use the value returned by the call.
-                   This is used for :
-                    - dispose of temp stack space
-                    - dispose on FPU stack
-                    - extended syntax checking }
-                 if (p.nodetype=calln) then
-                   begin
-                     exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
-
-                     { in $x- state, the function result must not be ignored }
-                     if not(cs_extsyntax in current_settings.moduleswitches) and
-                        not(is_void(p.resultdef)) and
-                        { can be nil in case there was an error in the expression }
-                        assigned(tcallnode(p).procdefinition) and
-                        { allow constructor calls to drop the result if they are
-                          called as instance methods instead of class methods }
-                        not(
-                          (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
-                          is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and
-                          assigned(tcallnode(p).methodpointer) and
-                          (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef)
-                        ) then
-                       Message(parser_e_illegal_expression);
-                   end;
                end;
+
              code:=p;
            end;
          end;
-         if assigned(code) and
-           { type checking makes no sense in a generic definition }
-           not(df_generic in current_procinfo.procdef.defoptions) then
+         if assigned(code) then
            begin
              typecheckpass(code);
              code.fileinfo:=filepos;

+ 1 - 3
compiler/psub.pas

@@ -1869,9 +1869,7 @@ implementation
              entrypos:=code.fileinfo;
 
              { Finish type checking pass }
-             { type checking makes no sense in a generic definition }
-             if not(df_generic in current_procinfo.procdef.defoptions) then
-               do_typecheckpass(code);
+             do_typecheckpass(code);
 
              if assigned(procdef.parentfpinitblock) then
                begin

+ 37 - 0
tests/tbs/tb0617.pp

@@ -0,0 +1,37 @@
+{ %NORUN }
+
+program tb0617;
+
+{$mode objfpc}
+
+type
+  generic TGenericStructList<T> = class
+  public
+    function Remove(const Item: T): Integer;
+    procedure Delete(Index: Integer);
+    function IndexOf(const Item: T): Integer;
+  end;
+
+function TGenericStructList.Remove(const Item: T): Integer;
+begin
+  Result := IndexOf(Item);
+  { for some reason, FPC 3.1.1 makes here incorrect warning:
+    castlegenericlists.pas(254,13) Warning: Function result variable does not seem to be initialized }
+  if Result >= 0 then
+    Delete(Result);
+end;
+
+function TGenericStructList.IndexOf(const Item: T): Integer;
+begin
+  Result := 0;
+end;
+
+procedure TGenericStructList.Delete(Index: Integer);
+begin
+
+end;
+
+
+begin
+
+end.