Browse Source

* correctly handle reading of class/object pointers in combination with @, resolves #26326

git-svn-id: trunk@43804 -
florian 5 years ago
parent
commit
00859420ab
4 changed files with 57 additions and 11 deletions
  1. 1 0
      .gitattributes
  2. 5 0
      compiler/htypechk.pas
  3. 20 11
      compiler/nmem.pas
  4. 31 0
      tests/webtbs/tw26326.pp

+ 1 - 0
.gitattributes

@@ -17318,6 +17318,7 @@ tests/webtbs/tw2627.pp svneol=native#text/plain
 tests/webtbs/tw26271.pp svneol=native#text/pascal
 tests/webtbs/tw26271.pp svneol=native#text/pascal
 tests/webtbs/tw26288.pp svneol=native#text/pascal
 tests/webtbs/tw26288.pp svneol=native#text/pascal
 tests/webtbs/tw2631.pp svneol=native#text/plain
 tests/webtbs/tw2631.pp svneol=native#text/plain
+tests/webtbs/tw26326.pp svneol=native#text/pascal
 tests/webtbs/tw26402.pp svneol=native#text/plain
 tests/webtbs/tw26402.pp svneol=native#text/plain
 tests/webtbs/tw26403.pp svneol=native#text/pascal
 tests/webtbs/tw26403.pp svneol=native#text/pascal
 tests/webtbs/tw26408.pp svneol=native#text/pascal
 tests/webtbs/tw26408.pp svneol=native#text/pascal

+ 5 - 0
compiler/htypechk.pas

@@ -1297,6 +1297,9 @@ implementation
                break;
                break;
              loadn :
              loadn :
                begin
                begin
+                 { the class pointer is read }
+                 if assigned(tunarynode(p).left) then
+                   set_varstate(tunarynode(p).left,vs_read,[vsf_must_be_valid]);
                  if (tloadnode(p).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) then
                  if (tloadnode(p).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) then
                    begin
                    begin
                      hsym:=tabstractvarsym(tloadnode(p).symtableentry);
                      hsym:=tabstractvarsym(tloadnode(p).symtableentry);
@@ -1377,6 +1380,8 @@ implementation
                  end;
                  end;
                  break;
                  break;
                end;
                end;
+             addrn:
+               break;
              callparan :
              callparan :
                internalerror(200310081);
                internalerror(200310081);
              else
              else

+ 20 - 11
compiler/nmem.pas

@@ -535,6 +535,22 @@ implementation
 
 
 
 
     function taddrnode.pass_typecheck:tnode;
     function taddrnode.pass_typecheck:tnode;
+
+      procedure check_mark_read_written;
+        begin
+          if mark_read_written then
+            begin
+              { This is actually only "read", but treat it nevertheless as
+                modified due to the possible use of pointers
+                To avoid false positives regarding "uninitialised"
+                warnings when using arrays, perform it in two steps         }
+              set_varstate(left,vs_written,[]);
+              { vsf_must_be_valid so it doesn't get changed into
+                vsf_referred_not_inited                          }
+              set_varstate(left,vs_read,[vsf_must_be_valid]);
+            end;
+        end;
+
       var
       var
          hp : tnode;
          hp : tnode;
          hsym : tfieldvarsym;
          hsym : tfieldvarsym;
@@ -629,9 +645,11 @@ implementation
               end
               end
             else
             else
               begin
               begin
+                check_mark_read_written;
                 { Return the typeconvn only }
                 { Return the typeconvn only }
                 result:=left;
                 result:=left;
                 left:=nil;
                 left:=nil;
+                exit;
               end;
               end;
           end
           end
         else
         else
@@ -650,17 +668,8 @@ implementation
               CGMessage(type_e_variable_id_expected);
               CGMessage(type_e_variable_id_expected);
           end;
           end;
 
 
-        if mark_read_written then
-          begin
-            { This is actually only "read", but treat it nevertheless as  }
-            { modified due to the possible use of pointers                }
-            { To avoid false positives regarding "uninitialised"          }
-            { warnings when using arrays, perform it in two steps         }
-            set_varstate(left,vs_written,[]);
-            { vsf_must_be_valid so it doesn't get changed into }
-            { vsf_referred_not_inited                          }
-            set_varstate(left,vs_read,[vsf_must_be_valid]);
-          end;
+        check_mark_read_written;
+
         if not(assigned(result)) then
         if not(assigned(result)) then
           result:=simplify(false);
           result:=simplify(false);
       end;
       end;

+ 31 - 0
tests/webtbs/tw26326.pp

@@ -0,0 +1,31 @@
+{ %opt=-vn -Sen }
+{ %norun }
+{$mode objfpc}
+type
+  TForm = class
+    procedure OnClick;
+  end;
+  
+  TNotifyEvent = procedure of object;
+  
+procedure TForm.OnClick;
+  begin
+  end;
+  
+  
+procedure Test (aObject: TObject);
+var
+  aForm: TForm;
+  aEvent: TNotifyEvent;
+begin
+  if (aObject is TForm) then
+  begin
+    aForm := aObject as TForm;
+    aEvent := @aForm.OnClick;
+    aEvent();
+  end;
+end; 
+
+begin
+  Test(nil);
+end.