فهرست منبع

* don't evaluate sizeof(<type param>) as a constant to avoid arithmetic errors in constant folding, resolves #20192

git-svn-id: trunk@19285 -
florian 14 سال پیش
والد
کامیت
9d31a0e2f8
3فایلهای تغییر یافته به همراه53 افزوده شده و 2 حذف شده
  1. 1 0
      .gitattributes
  2. 5 2
      compiler/pexpr.pas
  3. 47 0
      tests/webtbs/tw20192.pp

+ 1 - 0
.gitattributes

@@ -11869,6 +11869,7 @@ tests/webtbs/tw2004.pp svneol=native#text/plain
 tests/webtbs/tw20093.pp svneol=native#text/pascal
 tests/webtbs/tw20093a.pp svneol=native#text/pascal
 tests/webtbs/tw20119.pp -text svneol=native#test/pascal
+tests/webtbs/tw20192.pp svneol=native#text/pascal
 tests/webtbs/tw20257.pp svneol=native#text/plain
 tests/webtbs/tw2028.pp svneol=native#text/plain
 tests/webtbs/tw2030.pp svneol=native#text/plain

+ 5 - 2
compiler/pexpr.pas

@@ -388,14 +388,17 @@ implementation
               in_args:=true;
               p1:=comp_expr(true,false);
               consume(_RKLAMMER);
-              if (p1.nodetype<>typen) and
+              if ((p1.nodetype<>typen) and
+
                  (
                   (is_object(p1.resultdef) and
                    (oo_has_constructor in tobjectdef(p1.resultdef).objectoptions)) or
                   is_open_array(p1.resultdef) or
                   is_array_of_const(p1.resultdef) or
                   is_open_string(p1.resultdef)
-                 ) then
+                 )) or
+                 { keep the function call if it is a type parameter to avoid arithmetic errors due to constant folding }
+                 (p1.resultdef.typ=undefineddef) then
                 begin
                   statement_syssym:=geninlinenode(in_sizeof_x,false,p1);
                   { no packed bit support for these things }

+ 47 - 0
tests/webtbs/tw20192.pp

@@ -0,0 +1,47 @@
+program SizeOfBug;
+{$mode objfpc}{$H+}
+
+type
+  generic TGen<_T> = class(TObject)
+    private
+      FField: _T;
+    public
+      constructor Create(Val: _T);
+
+      function Bug: Integer;
+  end;
+
+{--- TGen.Create ---}
+constructor TGen.Create(Val: _T);
+begin
+  inherited Create;
+  FField := Val;
+end;
+
+{--- TGen.Bug ---}
+function TGen.Bug : Integer;
+begin
+  Result := 100000 div SizeOf(_T);  // *** DIVISION BY ZERO ***
+
+  // THE FOLLOWING CODE IS OK !
+  //
+  // var
+  //   S: Integer;
+  // begin
+  //   S := SizeOf(_T);
+  //   Result := 100000 div S;
+end;
+
+type
+  TGenInt = specialize TGen<Integer>;
+
+var
+  V: TGenInt;
+begin
+  V := V.Create(589);
+  WriteLn('V.Bug = ', V.Bug);
+  if V.Bug<>100000 div sizeof(pointer) then
+    halt(1);
+  V.Free;
+  writeln('ok');
+end.