Ver código fonte

* accept dereferences in generics definitions, resolves #33700 properly

git-svn-id: trunk@39447 -
florian 7 anos atrás
pai
commit
93c5eae528
4 arquivos alterados com 90 adições e 3 exclusões
  1. 1 0
      .gitattributes
  2. 4 2
      compiler/nmem.pas
  3. 1 1
      compiler/pexpr.pas
  4. 84 0
      tests/webtbs/tw33700.pp

+ 1 - 0
.gitattributes

@@ -16210,6 +16210,7 @@ tests/webtbs/tw33635.pp svneol=native#text/pascal
 tests/webtbs/tw3364.pp svneol=native#text/plain
 tests/webtbs/tw3366.pp svneol=native#text/plain
 tests/webtbs/tw33696.pp svneol=native#text/pascal
+tests/webtbs/tw33700.pp svneol=native#text/pascal
 tests/webtbs/tw33706.pp svneol=native#text/plain
 tests/webtbs/tw33818.pp svneol=native#text/pascal
 tests/webtbs/tw33839a.pp -text svneol=native#text/pascal

+ 4 - 2
compiler/nmem.pas

@@ -769,9 +769,11 @@ implementation
          maybe_call_procvar(left,true);
 
          if left.resultdef.typ=pointerdef then
-          resultdef:=tpointerdef(left.resultdef).pointeddef
+           resultdef:=tpointerdef(left.resultdef).pointeddef
+         else if left.resultdef.typ=undefineddef then
+           resultdef:=cundefineddef.create(true)
          else
-          CGMessage(parser_e_invalid_qualifier);
+           CGMessage(parser_e_invalid_qualifier);
       end;
 
     procedure Tderefnode.mark_write;

+ 1 - 1
compiler/pexpr.pas

@@ -2034,7 +2034,7 @@ implementation
                        end;
                    end;
                  end
-               else if (p1.resultdef.typ<>pointerdef) then
+               else if not(p1.resultdef.typ in [pointerdef,undefineddef]) then
                  begin
                     { ^ as binary operator is a problem!!!! (FK) }
                     again:=false;

+ 84 - 0
tests/webtbs/tw33700.pp

@@ -0,0 +1,84 @@
+program testbug;
+{$mode delphi}{$H+}
+type
+  PLstGrandTyp = ^TLstGrandForwardTyp;
+
+  TLstGrandForwardTyp = packed record
+    early, Next: PLstGrandTyp;
+  end;
+
+
+  PLstTyp01 = ^TLstForwardTyp01;
+  TLstForwardTyp01 = packed record
+    early, Next: PLstTyp01;
+    Value: byte;
+  end;
+
+  PLstTyp02 = ^TLstForwardTyp02;
+  TLstForwardTyp02 = packed record
+    early, Next: PLstTyp02;
+    Value: string[255];
+  end;
+
+  TLstEnumerator<T> = record
+  private
+    lst, lst_save: T;
+  public
+    constructor Create(const Value: T);
+    function GetEnumerator: TLstEnumerator<T>;
+    function MoveNext: boolean;
+    property Current: T read lst;
+  end;
+
+constructor TLstEnumerator<T>.Create(const Value: T);
+begin
+  lst := Value;
+  lst_save := nil;
+end;
+
+function TLstEnumerator<T>.GetEnumerator: TLstEnumerator<T>;
+begin
+  Result := Self;
+end;
+
+function TLstEnumerator<T>.MoveNext: boolean;
+begin
+  if lst <> nil then
+  begin
+    // At this point it is simply not known that lst is a type that has
+    // a field called next. So the compiler throws an illegal qualifier.
+    // The compiler is correct. This is not a bug!
+    lst:=lst^.next;
+    Result := True;
+  end else Result := False;
+end;
+
+
+var
+  i01:PLstTyp01 = nil;
+  lst01: PLstTyp01 = nil;
+  i02:PlstTyp02 = nil;
+  lst02: PLstTyp02 = nil;
+  i03:PlstGrandTyp = nil;
+  lst03: PLstGrandTyp = nil;
+  en01: TLstEnumerator<PLstTyp01>;
+  en02: TLstEnumerator<PLstTyp02>;
+  en03: TLstEnumerator<PLstGrandTyp>;
+begin
+
+  for i01 in en01.Create(lst01) do
+  begin
+    i01^.Value := 10;
+  end;
+
+  for i02 in en02.Create(lst02) do
+  begin
+    i02^.Value := 'ten';
+  end;
+
+  for i03 in en03.Create(lst03) do
+  begin
+  end;
+
+end.
+