Explorar el Código

* handle pointer+type param. correctly, resolves #19548
* convert exit(x) into result:=x; exit;, enables further optimizations in the future

git-svn-id: trunk@17829 -

florian hace 14 años
padre
commit
6e1d5e0aa0
Se han modificado 5 ficheros con 49 adiciones y 8 borrados
  1. 1 0
      .gitattributes
  2. 7 0
      compiler/defutil.pas
  3. 7 0
      compiler/nadd.pas
  4. 13 8
      compiler/nflw.pas
  5. 21 0
      tests/webtbs/tw19548.pp

+ 1 - 0
.gitattributes

@@ -11678,6 +11678,7 @@ tests/webtbs/tw1936.pp svneol=native#text/plain
 tests/webtbs/tw1938.pp svneol=native#text/plain
 tests/webtbs/tw1948.pp svneol=native#text/plain
 tests/webtbs/tw1950.pp svneol=native#text/plain
+tests/webtbs/tw19548.pp svneol=native#text/pascal
 tests/webtbs/tw1964.pp svneol=native#text/plain
 tests/webtbs/tw1996.pp svneol=native#text/plain
 tests/webtbs/tw2001.pp svneol=native#text/plain

+ 7 - 0
compiler/defutil.pas

@@ -265,6 +265,9 @@ interface
         or not }
     function is_nested_pd(def: tabstractprocdef): boolean;{$ifdef USEINLINE}inline;{$endif}
 
+    { # returns whether def is a type parameter of a generic }
+    function is_typeparam(def : tdef) : boolean;{$ifdef USEINLINE}inline;{$endif}
+
 implementation
 
     uses
@@ -1142,4 +1145,8 @@ implementation
       end;
 
 
+    function is_typeparam(def : tdef) : boolean;{$ifdef USEINLINE}inline;{$endif}
+      begin
+        result:=(def.typ=undefineddef);
+      end;
 end.

+ 7 - 0
compiler/nadd.pas

@@ -826,6 +826,13 @@ implementation
 
       begin
          result:=nil;
+         { avoid any problems with type parameters later on }
+         if is_typeparam(left.resultdef) or is_typeparam(right.resultdef) then
+           begin
+             resultdef:=cundefinedtype;
+             exit;
+           end;
+
          { both left and right need to be valid }
          set_varstate(left,vs_read,[vsf_must_be_valid]);
          set_varstate(right,vs_read,[vsf_must_be_valid]);

+ 13 - 8
compiler/nflw.pas

@@ -1070,7 +1070,8 @@ implementation
          if codegenerror then
            exit;
 
-         if not is_boolean(left.resultdef) then
+         if not(is_boolean(left.resultdef)) and
+           not(is_typeparam(left.resultdef)) then
            begin
              if left.resultdef.typ=variantdef then
                inserttypeconv(left,booltype)
@@ -1382,7 +1383,8 @@ implementation
          if codegenerror then
            exit;
 
-         if not is_boolean(left.resultdef) then
+         if not(is_boolean(left.resultdef)) and
+           not(is_typeparam(left.resultdef)) then
            begin
              if left.resultdef.typ=variantdef then
                inserttypeconv(left,booltype)
@@ -1569,10 +1571,17 @@ implementation
 
 
     function texitnode.pass_typecheck:tnode;
+      var
+        newstatement : tstatementnode;
       begin
         result:=nil;
         if assigned(left) then
-          typecheckpass(left);
+          begin
+             result:=internalstatements(newstatement);
+             addstatement(newstatement,left);
+             left:=nil;
+             addstatement(newstatement,self.getcopy);
+          end;
         resultdef:=voidtype;
       end;
 
@@ -1582,11 +1591,7 @@ implementation
          result:=nil;
          expectloc:=LOC_VOID;
          if assigned(left) then
-           begin
-              firstpass(left);
-              if codegenerror then
-               exit;
-           end;
+           internalerror(2011052801);
       end;
 
 

+ 21 - 0
tests/webtbs/tw19548.pp

@@ -0,0 +1,21 @@
+{$MODE OBJFPC} { -*- text -*- }
+program tests;
+
+type
+   generic TTest <PTest> = class
+     FPointer: PTest;
+     procedure Foo();
+   end;
+
+procedure TTest.Foo();
+var
+   Result: Boolean;
+begin
+   Result := FPointer = nil;
+end;
+
+type
+  TPointerTest = specialize TTest <Pointer>;
+
+begin
+end.