Browse Source

* fix #40634: correctly check visibility for child classes in case of a mixture of specializations and non-specializations
+ added test

Sven/Sarah Barth 1 year ago
parent
commit
d9903e6e16
4 changed files with 212 additions and 2 deletions
  1. 39 2
      compiler/symtable.pas
  2. 24 0
      tests/webtbs/tw40634.pp
  3. 80 0
      tests/webtbs/uw40634a.pp
  4. 69 0
      tests/webtbs/uw40634b.pp

+ 39 - 2
compiler/symtable.pas

@@ -3264,6 +3264,8 @@ implementation
         end;
         end;
 
 
       var
       var
+        orgcontextobjdef,
+        orgsymownerdef,
         symownerdef : tabstractrecorddef;
         symownerdef : tabstractrecorddef;
         nonlocalst : tsymtable;
         nonlocalst : tsymtable;
         isspezproc : boolean;
         isspezproc : boolean;
@@ -3275,6 +3277,8 @@ implementation
            not (symst.symtabletype in [objectsymtable,recordsymtable]) then
            not (symst.symtabletype in [objectsymtable,recordsymtable]) then
           internalerror(200810285);
           internalerror(200810285);
         symownerdef:=tabstractrecorddef(symst.defowner);
         symownerdef:=tabstractrecorddef(symst.defowner);
+        orgsymownerdef:=symownerdef;
+        orgcontextobjdef:=contextobjdef;
         { for specializations we need to check the visibility of the generic,
         { for specializations we need to check the visibility of the generic,
           not the specialization (at least when comparing outside of the
           not the specialization (at least when comparing outside of the
           specialization }
           specialization }
@@ -3282,12 +3286,14 @@ implementation
           begin
           begin
             if not (symownerdef.genericdef.typ in [objectdef,recorddef]) then
             if not (symownerdef.genericdef.typ in [objectdef,recorddef]) then
               internalerror(2024020901);
               internalerror(2024020901);
+            orgsymownerdef:=symownerdef;
             symownerdef:=tabstractrecorddef(symownerdef.genericdef);
             symownerdef:=tabstractrecorddef(symownerdef.genericdef);
           end;
           end;
         if assigned(contextobjdef) and (df_specialization in contextobjdef.defoptions) then
         if assigned(contextobjdef) and (df_specialization in contextobjdef.defoptions) then
           begin
           begin
             if not (contextobjdef.genericdef.typ in [objectdef,recorddef]) then
             if not (contextobjdef.genericdef.typ in [objectdef,recorddef]) then
               internalerror(2024020902);
               internalerror(2024020902);
+            orgcontextobjdef:=contextobjdef;
             contextobjdef:=tabstractrecorddef(contextobjdef.genericdef);
             contextobjdef:=tabstractrecorddef(contextobjdef.genericdef);
           end;
           end;
         if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
         if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
@@ -3355,17 +3361,34 @@ implementation
           vis_strictprotected :
           vis_strictprotected :
             begin
             begin
                result:=(
                result:=(
-                         { access from nested class }
+                         { access from nested class (specialization case) }
                          assigned(curstruct) and
                          assigned(curstruct) and
                          is_owned_by(curstruct,symownerdef)
                          is_owned_by(curstruct,symownerdef)
                        ) or
                        ) or
                        (
                        (
-                         { access from child class }
+                         { access from nested class (non-specialization case) }
+                         (orgsymownerdef<>symownerdef) and
+                         assigned(curstruct) and
+                         is_owned_by(curstruct,orgsymownerdef)
+                       ) or
+                       (
+                         { access from child class (specialization case) }
                          assigned(contextobjdef) and
                          assigned(contextobjdef) and
                          assigned(curstruct) and
                          assigned(curstruct) and
                          def_is_related(contextobjdef,symownerdef) and
                          def_is_related(contextobjdef,symownerdef) and
                          def_is_related(curstruct,contextobjdef)
                          def_is_related(curstruct,contextobjdef)
                        ) or
                        ) or
+                       (
+                         { access from child class (non-specialization case) }
+                         assigned(orgcontextobjdef) and
+                         (
+                           (orgcontextobjdef<>contextobjdef) or
+                           (orgsymownerdef<>symownerdef)
+                         ) and
+                         assigned(curstruct) and
+                         def_is_related(orgcontextobjdef,orgsymownerdef) and
+                         def_is_related(curstruct,orgcontextobjdef)
+                       ) or
                        (
                        (
                          { helpers can access strict protected symbols }
                          { helpers can access strict protected symbols }
                          is_objectpascal_helper(contextobjdef) and
                          is_objectpascal_helper(contextobjdef) and
@@ -3389,11 +3412,25 @@ implementation
                         is_current_unit(nonlocalst)
                         is_current_unit(nonlocalst)
                        ) or
                        ) or
                        (
                        (
+                        { context object is inside the current unit and related to
+                          the symbol owner (specialization case) }
                         assigned(contextobjdef) and
                         assigned(contextobjdef) and
                         (contextobjdef.owner.symtabletype in [globalsymtable,staticsymtable,ObjectSymtable,recordsymtable,localsymtable]) and
                         (contextobjdef.owner.symtabletype in [globalsymtable,staticsymtable,ObjectSymtable,recordsymtable,localsymtable]) and
                         is_current_unit(contextobjdef.owner) and
                         is_current_unit(contextobjdef.owner) and
                         def_is_related(contextobjdef,symownerdef)
                         def_is_related(contextobjdef,symownerdef)
                        ) or
                        ) or
+                       (
+                        { context object is inside the current unit and related to
+                          the symbol owner (non-specialization case) }
+                        assigned(orgcontextobjdef) and
+                        (
+                          (orgcontextobjdef<>contextobjdef) or
+                          (orgsymownerdef<>symownerdef)
+                        ) and
+                        (orgcontextobjdef.owner.symtabletype in [globalsymtable,staticsymtable,ObjectSymtable,recordsymtable,localsymtable]) and
+                        is_current_unit(orgcontextobjdef.owner) and
+                        def_is_related(orgcontextobjdef,orgsymownerdef)
+                       ) or
                        ( // the case of specialize inside the generic declaration and nested types
                        ( // the case of specialize inside the generic declaration and nested types
                         (nonlocalst.symtabletype in [objectsymtable,recordsymtable]) and
                         (nonlocalst.symtabletype in [objectsymtable,recordsymtable]) and
                         (
                         (

+ 24 - 0
tests/webtbs/tw40634.pp

@@ -0,0 +1,24 @@
+{ %NORUN }
+
+program tw40634;
+{$mode objfpc}{$H+}
+uses uw40634a, uw40634b;
+
+type
+  TWatchesSupplier = class(specialize TWatchesSupplierClassTemplate<TObject>, IDbgWatchesSupplierIntf)
+  //TWatchesSupplier = class(specialize TWatchesSupplierClassTemplate<TObject>)
+  //TWatchesSupplier = class(TNormalClass, IDbgWatchesSupplierIntf)
+  protected
+    procedure DoFoo;
+  end;
+
+{ TWatchesSupplier }
+
+procedure TWatchesSupplier.DoFoo;
+begin
+  if Monitor <> nil then;
+end;
+
+begin
+end.
+

+ 80 - 0
tests/webtbs/uw40634a.pp

@@ -0,0 +1,80 @@
+{***************************************************************************
+ *                                                                         *
+ * This unit is distributed under the LGPL version 2                       *
+ *                                                                         *
+ * Additionally this unit can be used under any newer version (3 or up)    *
+ * of the LGPL                                                             *
+ *                                                                         *
+ * Users are also granted the same "linking exception" as defined          *
+ * for the LCL.                                                            *
+ * See the LCL license for details                                         *
+ *                                                                         *
+ *                                                                         *
+ ***************************************************************************
+ @author(Martin Friebe)
+}
+unit uw40634a;
+
+{$mode objfpc}{$H+}
+{$INTERFACES CORBA} // no ref counting needed
+
+interface
+
+uses
+  Classes, SysUtils, uw40634b;
+
+type
+
+TNormalClass = class
+  strict protected
+    procedure SetMonitor(AMonitor: IDbgWatchesMonitorIntf); virtual; abstract;
+    procedure RequestData(AWatchValue: IDbgWatchValueIntf); virtual; abstract;
+    function Monitor:TObject;virtual; abstract;
+end;
+
+  { TInternalDbgSupplierBase }
+
+  generic TInternalDbgSupplierBase<
+    _BASE: TObject;
+    _SUPPLIER_INTF: IInternalDbgSupplierIntfType;
+    _MONITOR_INTF //: IInternalDbgMonitorIntfType
+    >
+    = class(_BASE)
+  strict private
+    FMonitor: _MONITOR_INTF;
+
+
+  // ********************************************************************************
+      (* "private" is CORRECTLY not working
+         all others should work, but have different error   *)
+
+  //private
+  strict protected
+    procedure SetMonitor1(AMonitor: _MONITOR_INTF);virtual; abstract;
+  protected
+    procedure SetMonitor2(AMonitor: _MONITOR_INTF);virtual; abstract;
+  public
+    procedure SetMonitor3(AMonitor: _MONITOR_INTF);virtual; abstract;
+  // ********************************************************************************
+  protected
+
+    property Monitor: _MONITOR_INTF read FMonitor;
+  end;
+
+type
+
+  { TWatchesSupplierClassTemplate }
+
+  generic TWatchesSupplierClassTemplate<_BASE: TObject> = class(
+    specialize TInternalDbgSupplierBase<_BASE, IDbgWatchesSupplierIntf, IDbgWatchesMonitorIntf>,
+    IDbgWatchesSupplierIntf
+  )
+  protected
+  public
+    procedure RequestData(AWatchValue: IDbgWatchValueIntf); virtual; abstract;
+  end;
+
+
+implementation
+
+end.

+ 69 - 0
tests/webtbs/uw40634b.pp

@@ -0,0 +1,69 @@
+{***************************************************************************
+ *                                                                         *
+ * This unit is distributed under the LGPL version 2                       *
+ *                                                                         *
+ * Additionally this unit can be used under any newer version (3 or up)    *
+ * of the LGPL                                                             *
+ *                                                                         *
+ * Users are also granted the same "linking exception" as defined          *
+ * for the LCL.                                                            *
+ * See the LCL license for details                                         *
+ *                                                                         *
+ *                                                                         *
+ ***************************************************************************
+ @author(Martin Friebe)
+}
+unit uw40634b;
+
+{$mode objfpc}{$H+}
+{$INTERFACES CORBA} // no ref counting needed
+
+interface
+
+uses
+  Classes, SysUtils, Types;
+
+type
+  TDBGState = integer;
+  IDbgWatchValueIntf = interface end;
+  IDbgWatchDataIntf = interface end;
+
+  {$REGION ***** Internal types ***** }
+
+  IInternalDbgMonitorIntfType  = interface end;
+  IInternalDbgSupplierIntfType = interface end;
+
+  generic IInternalDbgMonitorIntf<_SUPPLIER_INTF> = interface(IInternalDbgMonitorIntfType)
+    procedure RemoveSupplier(ASupplier: _SUPPLIER_INTF);
+  end;
+
+  generic IInternalDbgSupplierIntf<_MONITOR_INTF> = interface(IInternalDbgSupplierIntfType)
+    procedure SetMonitor1(AMonitor: _MONITOR_INTF);
+    procedure SetMonitor2(AMonitor: _MONITOR_INTF);
+    procedure SetMonitor3(AMonitor: _MONITOR_INTF);
+  end;
+
+  {$ENDREGION}
+
+type
+
+  IDbgWatchesSupplierIntf = interface;
+
+  IDbgWatchesMonitorIntf  = interface(specialize IInternalDbgMonitorIntf<IDbgWatchesSupplierIntf>)
+    ['{42A7069E-D5DD-4350-A592-2000F67DC7E9}']
+    procedure InvalidateWatchValues;
+    procedure DoStateChange(const AOldState, ANewState: TDBGState); //deprecated;
+  end;
+
+  IDbgWatchesSupplierIntf = interface(specialize IInternalDbgSupplierIntf<IDbgWatchesMonitorIntf>)
+    ['{F893B607-C295-4A3A-8253-FAB3D03C5AD5}']
+    procedure RequestData(AWatchValue: IDbgWatchValueIntf);
+  end;
+
+
+
+implementation
+
+
+end.
+