Browse Source

* do not call typecheckpass unncessarily in generic definitions, it might cause only errors, resolves #28058

git-svn-id: trunk@31262 -
florian 10 years ago
parent
commit
9a55e8fa3c
4 changed files with 71 additions and 42 deletions
  1. 1 0
      .gitattributes
  2. 47 41
      compiler/pstatmnt.pas
  3. 3 1
      compiler/psub.pas
  4. 20 0
      tests/webtbs/tw28058.pp

+ 1 - 0
.gitattributes

@@ -14661,6 +14661,7 @@ tests/webtbs/tw27998.pp svneol=native#text/plain
 tests/webtbs/tw27998a.pp svneol=native#text/plain
 tests/webtbs/tw27998a.pp svneol=native#text/plain
 tests/webtbs/tw28007.pp svneol=native#text/pascal
 tests/webtbs/tw28007.pp svneol=native#text/pascal
 tests/webtbs/tw2803.pp svneol=native#text/plain
 tests/webtbs/tw2803.pp svneol=native#text/plain
+tests/webtbs/tw28058.pp svneol=native#text/pascal
 tests/webtbs/tw2806.pp svneol=native#text/plain
 tests/webtbs/tw2806.pp svneol=native#text/plain
 tests/webtbs/tw2807.pp svneol=native#text/plain
 tests/webtbs/tw2807.pp svneol=native#text/plain
 tests/webtbs/tw28089.pp svneol=native#text/plain
 tests/webtbs/tw28089.pp svneol=native#text/plain

+ 47 - 41
compiler/pstatmnt.pas

@@ -1284,53 +1284,59 @@ implementation
              if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
              if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
                maybe_call_procvar(p,false);
                maybe_call_procvar(p,false);
 
 
-             { 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
+             { additional checks make no sense in a generic definition }
+             if not(df_generic in current_procinfo.procdef.defoptions) then
                begin
                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
+                 { 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);
                    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;
                end;
              code:=p;
              code:=p;
            end;
            end;
          end;
          end;
-         if assigned(code) then
+         if assigned(code) and
+           { type checking makes no sense in a generic definition }
+           not(df_generic in current_procinfo.procdef.defoptions) then
            begin
            begin
              typecheckpass(code);
              typecheckpass(code);
              code.fileinfo:=filepos;
              code.fileinfo:=filepos;

+ 3 - 1
compiler/psub.pas

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

+ 20 - 0
tests/webtbs/tw28058.pp

@@ -0,0 +1,20 @@
+{$mode objfpc}
+program Project1;
+type
+  generic TFoo<T> = class
+  const
+    Size = SizeOf(T);
+   public
+     function X: Integer;
+  end;
+
+{ TFoo }
+
+function TFoo.X: Integer;
+begin
+  //Result := 100 div SizeOf(T);
+  Result := 100 div Size;
+end;
+
+begin
+end.