mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-08 09:59:12 +02:00
* fix #40621: when checking for visibility of members then always use the genericdefs for specializations for correct scoping
+ added test
This commit is contained in:
parent
ed8a05d697
commit
43721f21c4
@ -3245,17 +3245,19 @@ implementation
|
||||
objfield.fieldname:=1 -> contextobjdef = def of objfield
|
||||
}
|
||||
function is_visible_for_object(symst:tsymtable;symvisibility:tvisibility;contextobjdef:tabstractrecorddef):boolean;
|
||||
var
|
||||
curstruct : tabstractrecorddef;
|
||||
|
||||
function is_current_unit(st:tsymtable):boolean;
|
||||
begin
|
||||
result :=
|
||||
(
|
||||
(
|
||||
assigned(current_structdef) and
|
||||
(st.moduleid=current_structdef.symtable.moduleid)
|
||||
assigned(curstruct) and
|
||||
(st.moduleid=curstruct.symtable.moduleid)
|
||||
) or
|
||||
(
|
||||
not assigned(current_structdef) and
|
||||
not assigned(curstruct) and
|
||||
st.iscurrentunit
|
||||
)
|
||||
);
|
||||
@ -3273,9 +3275,32 @@ implementation
|
||||
not (symst.symtabletype in [objectsymtable,recordsymtable]) then
|
||||
internalerror(200810285);
|
||||
symownerdef:=tabstractrecorddef(symst.defowner);
|
||||
{ for specializations we need to check the visibility of the generic,
|
||||
not the specialization (at least when comparing outside of the
|
||||
specialization }
|
||||
if df_specialization in symownerdef.defoptions then
|
||||
begin
|
||||
if not (symownerdef.genericdef.typ in [objectdef,recorddef]) then
|
||||
internalerror(2024020901);
|
||||
symownerdef:=tabstractrecorddef(symownerdef.genericdef);
|
||||
end;
|
||||
if assigned(contextobjdef) and (df_specialization in contextobjdef.defoptions) then
|
||||
begin
|
||||
if not (contextobjdef.genericdef.typ in [objectdef,recorddef]) then
|
||||
internalerror(2024020902);
|
||||
contextobjdef:=tabstractrecorddef(contextobjdef.genericdef);
|
||||
end;
|
||||
if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
|
||||
begin
|
||||
if not (current_structdef.genericdef.typ in [objectdef,recorddef]) then
|
||||
internalerror(2024030903);
|
||||
curstruct:=tabstractrecorddef(current_structdef.genericdef)
|
||||
end
|
||||
else
|
||||
curstruct:=current_structdef;
|
||||
{ specializations might belong to a localsymtable or parasymtable }
|
||||
nonlocalst:=symownerdef.owner;
|
||||
if tstoreddef(symst.defowner).is_specialization then
|
||||
if tstoreddef(symownerdef).is_specialization then
|
||||
while nonlocalst.symtabletype in [localsymtable,parasymtable] do
|
||||
nonlocalst:=nonlocalst.defowner.owner;
|
||||
isspezproc:=false;
|
||||
@ -3297,49 +3322,49 @@ implementation
|
||||
( // the case of specialize inside the generic declaration and nested types
|
||||
(nonlocalst.symtabletype in [objectsymtable,recordsymtable]) and
|
||||
(
|
||||
assigned(current_structdef) and
|
||||
assigned(curstruct) and
|
||||
(
|
||||
(current_structdef=symownerdef) or
|
||||
(current_structdef.owner.moduleid=symownerdef.symtable.moduleid)
|
||||
(curstruct=symownerdef) or
|
||||
(curstruct.owner.moduleid=symownerdef.symtable.moduleid)
|
||||
)
|
||||
) or
|
||||
(
|
||||
not assigned(current_structdef) and
|
||||
not assigned(curstruct) and
|
||||
(symownerdef.owner.iscurrentunit)
|
||||
) or
|
||||
{ access from a generic method that belongs to the class
|
||||
but that is specialized elsewere }
|
||||
(
|
||||
isspezproc and
|
||||
(current_procinfo.procdef.struct=current_structdef)
|
||||
(current_procinfo.procdef.struct=curstruct)
|
||||
) or
|
||||
{ specializations may access private symbols that their
|
||||
generics are allowed to access }
|
||||
(
|
||||
assigned(current_structdef) and
|
||||
(df_specialization in current_structdef.defoptions) and
|
||||
(symst.moduleid=current_structdef.genericdef.owner.moduleid)
|
||||
assigned(curstruct) and
|
||||
(df_specialization in curstruct.defoptions) and
|
||||
(symst.moduleid=curstruct.genericdef.owner.moduleid)
|
||||
)
|
||||
);
|
||||
end;
|
||||
vis_strictprivate :
|
||||
begin
|
||||
result:=assigned(current_structdef) and
|
||||
is_owned_by(current_structdef,symownerdef);
|
||||
result:=assigned(curstruct) and
|
||||
is_owned_by(curstruct,symownerdef);
|
||||
end;
|
||||
vis_strictprotected :
|
||||
begin
|
||||
result:=(
|
||||
{ access from nested class }
|
||||
assigned(current_structdef) and
|
||||
is_owned_by(current_structdef,symownerdef)
|
||||
assigned(curstruct) and
|
||||
is_owned_by(curstruct,symownerdef)
|
||||
) or
|
||||
(
|
||||
{ access from child class }
|
||||
assigned(contextobjdef) and
|
||||
assigned(current_structdef) and
|
||||
assigned(curstruct) and
|
||||
def_is_related(contextobjdef,symownerdef) and
|
||||
def_is_related(current_structdef,contextobjdef)
|
||||
def_is_related(curstruct,contextobjdef)
|
||||
) or
|
||||
(
|
||||
{ helpers can access strict protected symbols }
|
||||
@ -3349,8 +3374,8 @@ implementation
|
||||
(
|
||||
{ same as above, but from context of call node inside
|
||||
helper method }
|
||||
is_objectpascal_helper(current_structdef) and
|
||||
def_is_related(tobjectdef(current_structdef).extendeddef,symownerdef)
|
||||
is_objectpascal_helper(curstruct) and
|
||||
def_is_related(tobjectdef(curstruct).extendeddef,symownerdef)
|
||||
);
|
||||
end;
|
||||
vis_protected :
|
||||
@ -3372,14 +3397,14 @@ implementation
|
||||
( // the case of specialize inside the generic declaration and nested types
|
||||
(nonlocalst.symtabletype in [objectsymtable,recordsymtable]) and
|
||||
(
|
||||
assigned(current_structdef) and
|
||||
assigned(curstruct) and
|
||||
(
|
||||
(current_structdef=symownerdef) or
|
||||
(current_structdef.owner.moduleid=symownerdef.symtable.moduleid)
|
||||
(curstruct=symownerdef) or
|
||||
(curstruct.owner.moduleid=symownerdef.symtable.moduleid)
|
||||
)
|
||||
) or
|
||||
(
|
||||
not assigned(current_structdef) and
|
||||
not assigned(curstruct) and
|
||||
(symownerdef.owner.iscurrentunit)
|
||||
) or
|
||||
(
|
||||
@ -3392,14 +3417,14 @@ implementation
|
||||
but that is specialized elsewere }
|
||||
(
|
||||
isspezproc and
|
||||
(current_procinfo.procdef.struct=current_structdef)
|
||||
(current_procinfo.procdef.struct=curstruct)
|
||||
) or
|
||||
{ specializations may access private symbols that their
|
||||
generics are allowed to access }
|
||||
(
|
||||
assigned(current_structdef) and
|
||||
(df_specialization in current_structdef.defoptions) and
|
||||
(symst.moduleid=current_structdef.genericdef.owner.moduleid)
|
||||
assigned(curstruct) and
|
||||
(df_specialization in curstruct.defoptions) and
|
||||
(symst.moduleid=curstruct.genericdef.owner.moduleid)
|
||||
)
|
||||
);
|
||||
end;
|
||||
@ -3414,9 +3439,9 @@ implementation
|
||||
begin
|
||||
{ capturers have access to anything as we assume checks were done
|
||||
before the procdef was inserted into the capturer }
|
||||
result:=assigned(current_structdef) and
|
||||
(current_structdef.typ=objectdef) and
|
||||
(oo_is_capturer in tobjectdef(current_structdef).objectoptions);
|
||||
result:=assigned(curstruct) and
|
||||
(curstruct.typ=objectdef) and
|
||||
(oo_is_capturer in tobjectdef(curstruct).objectoptions);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
16
tests/webtbf/tw40621.pp
Normal file
16
tests/webtbf/tw40621.pp
Normal file
@ -0,0 +1,16 @@
|
||||
{ %FAIL }
|
||||
|
||||
program tw40621;
|
||||
{$mode delphi}{$H+}
|
||||
uses uw40621;
|
||||
|
||||
var
|
||||
X: TRecord< int32 >; // declared in unitFault
|
||||
|
||||
begin
|
||||
X.PrivateMember := 'Should not be able to assign this.';
|
||||
//Writeln( X.PrivateMember );
|
||||
//Readln;
|
||||
end.
|
||||
|
||||
|
14
tests/webtbf/uw40621.pp
Normal file
14
tests/webtbf/uw40621.pp
Normal file
@ -0,0 +1,14 @@
|
||||
unit uw40621;
|
||||
{$mode delphiunicode}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TRecord< T > = record
|
||||
private
|
||||
PrivateMember: string;
|
||||
end;
|
||||
|
||||
implementation
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user