浏览代码

* skip dec/inc type checking in unspecialized generic methods, resolves #25603

git-svn-id: trunk@26830 -
florian 11 年之前
父节点
当前提交
ab3f5744e0
共有 3 个文件被更改,包括 90 次插入58 次删除
  1. 1 0
      .gitattributes
  2. 61 58
      compiler/ninl.pas
  3. 28 0
      tests/webtbs/tw25603.pp

+ 1 - 0
.gitattributes

@@ -13820,6 +13820,7 @@ tests/webtbs/tw25398.pp svneol=native#text/plain
 tests/webtbs/tw2540.pp svneol=native#text/plain
 tests/webtbs/tw2540.pp svneol=native#text/plain
 tests/webtbs/tw25551.pp svneol=native#text/plain
 tests/webtbs/tw25551.pp svneol=native#text/plain
 tests/webtbs/tw25598.pp svneol=native#text/plain
 tests/webtbs/tw25598.pp svneol=native#text/plain
+tests/webtbs/tw25603.pp svneol=native#text/pascal
 tests/webtbs/tw2561.pp svneol=native#text/plain
 tests/webtbs/tw2561.pp svneol=native#text/plain
 tests/webtbs/tw25685.pp svneol=native#text/pascal
 tests/webtbs/tw25685.pp svneol=native#text/pascal
 tests/webtbs/tw2588.pp svneol=native#text/plain
 tests/webtbs/tw2588.pp svneol=native#text/plain

+ 61 - 58
compiler/ninl.pas

@@ -2846,72 +2846,75 @@ implementation
               in_dec_x:
               in_dec_x:
                 begin
                 begin
                   resultdef:=voidtype;
                   resultdef:=voidtype;
-                  if assigned(left) then
+                  if not(df_generic in current_procinfo.procdef.defoptions) then
                     begin
                     begin
-                       { first param must be var }
-                       valid_for_var(tcallparanode(left).left,true);
-                       set_varstate(tcallparanode(left).left,vs_readwritten,[vsf_must_be_valid]);
-
-                       if (left.resultdef.typ in [enumdef,pointerdef]) or
-                          is_ordinal(left.resultdef) or
-                          is_currency(left.resultdef) then
+                      if assigned(left) then
                         begin
                         begin
-                          { value of left gets changed -> must be unique }
-                          set_unique(tcallparanode(left).left);
-                          { two paras ? }
-                          if assigned(tcallparanode(left).right) then
-                           begin
-                             if is_integer(tcallparanode(left).right.resultdef) then
+                           { first param must be var }
+                           valid_for_var(tcallparanode(left).left,true);
+                           set_varstate(tcallparanode(left).left,vs_readwritten,[vsf_must_be_valid]);
+
+                           if (left.resultdef.typ in [enumdef,pointerdef]) or
+                              is_ordinal(left.resultdef) or
+                              is_currency(left.resultdef) then
+                            begin
+                              { value of left gets changed -> must be unique }
+                              set_unique(tcallparanode(left).left);
+                              { two paras ? }
+                              if assigned(tcallparanode(left).right) then
                                begin
                                begin
-                                 set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
-                                 { when range/overflow checking is on, we
-                                   convert this to a regular add, and for proper
-                                   checking we need the original type }
-                                 if ([cs_check_range,cs_check_overflow]*current_settings.localswitches=[]) then
-                                   if (tcallparanode(left).left.resultdef.typ=pointerdef) then
-                                     begin
-                                       { don't convert values added to pointers into the pointer types themselves,
-                                         because that will turn signed values into unsigned ones, which then
-                                         goes wrong when they have to be multiplied with the size of the elements
-                                         to which the pointer points in ncginl (mantis #17342) }
-                                       if is_signed(tcallparanode(tcallparanode(left).right).left.resultdef) then
-                                         inserttypeconv(tcallparanode(tcallparanode(left).right).left,ptrsinttype)
+                                 if is_integer(tcallparanode(left).right.resultdef) then
+                                   begin
+                                     set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
+                                     { when range/overflow checking is on, we
+                                       convert this to a regular add, and for proper
+                                       checking we need the original type }
+                                     if ([cs_check_range,cs_check_overflow]*current_settings.localswitches=[]) then
+                                       if (tcallparanode(left).left.resultdef.typ=pointerdef) then
+                                         begin
+                                           { don't convert values added to pointers into the pointer types themselves,
+                                             because that will turn signed values into unsigned ones, which then
+                                             goes wrong when they have to be multiplied with the size of the elements
+                                             to which the pointer points in ncginl (mantis #17342) }
+                                           if is_signed(tcallparanode(tcallparanode(left).right).left.resultdef) then
+                                             inserttypeconv(tcallparanode(tcallparanode(left).right).left,ptrsinttype)
+                                           else
+                                             inserttypeconv(tcallparanode(tcallparanode(left).right).left,ptruinttype)
+                                         end
+                                       else if is_integer(tcallparanode(left).left.resultdef) then
+                                         inserttypeconv(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef)
                                        else
                                        else
-                                         inserttypeconv(tcallparanode(tcallparanode(left).right).left,ptruinttype)
-                                     end
-                                   else if is_integer(tcallparanode(left).left.resultdef) then
-                                     inserttypeconv(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef)
-                                   else
-                                     inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef);
-                                 if assigned(tcallparanode(tcallparanode(left).right).right) then
-                                   { should be handled in the parser (JM) }
-                                   internalerror(2006020901);
-                               end
-                             else
-                               CGMessagePos(tcallparanode(left).right.fileinfo,type_e_ordinal_expr_expected);
-                           end;
-                        end
-                       { generic type parameter? }
-                       else if is_typeparam(left.resultdef) then
-                         begin
-                           result:=cnothingnode.create;
-                           exit;
-                         end
-                       else
-                         begin
-                           hp:=self;
-                           if isunaryoverloaded(hp) then
+                                         inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef);
+                                     if assigned(tcallparanode(tcallparanode(left).right).right) then
+                                       { should be handled in the parser (JM) }
+                                       internalerror(2006020901);
+                                   end
+                                 else
+                                   CGMessagePos(tcallparanode(left).right.fileinfo,type_e_ordinal_expr_expected);
+                               end;
+                            end
+                           { generic type parameter? }
+                           else if is_typeparam(left.resultdef) then
                              begin
                              begin
-                               { inc(rec) and dec(rec) assigns result value to argument }
-                               result:=cassignmentnode.create(tcallparanode(left).left.getcopy,hp);
+                               result:=cnothingnode.create;
                                exit;
                                exit;
                              end
                              end
                            else
                            else
-                             CGMessagePos(left.fileinfo,type_e_ordinal_expr_expected);
-                         end;
-                    end
-                  else
-                    CGMessagePos(fileinfo,type_e_mismatch);
+                             begin
+                               hp:=self;
+                               if isunaryoverloaded(hp) then
+                                 begin
+                                   { inc(rec) and dec(rec) assigns result value to argument }
+                                   result:=cassignmentnode.create(tcallparanode(left).left.getcopy,hp);
+                                   exit;
+                                 end
+                               else
+                                 CGMessagePos(left.fileinfo,type_e_ordinal_expr_expected);
+                             end;
+                        end
+                      else
+                        CGMessagePos(fileinfo,type_e_mismatch);
+                    end;
                 end;
                 end;
 
 
               in_read_x,
               in_read_x,

+ 28 - 0
tests/webtbs/tw25603.pp

@@ -0,0 +1,28 @@
+{$MODE DELPHI}
+
+type
+  TA = class
+    const C = 1;
+  end;
+
+  TB<T> = class
+    procedure Foo;
+  end;
+
+procedure TB<T>.Foo;
+var
+  i: Integer = 0;
+begin
+  // i := i + T.C; // <- is ok
+  Inc(i, T.C); // Error: Incompatible types: got "untyped" expected "LongInt"
+  if i<>1 then
+    halt(1);
+end;
+var
+  B : TB<TA>;
+begin
+  B:=TB<TA>.Create;
+  B.Foo;
+  B.Free;
+  writeln('ok');
+end.