Skip to content

Commit

Permalink
A type predicate object can only be seen from within the type definit…
Browse files Browse the repository at this point in the history
…ion.
  • Loading branch information
Roldak committed Oct 27, 2023
1 parent 3c459e5 commit 1dddaf7
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
22 changes: 13 additions & 9 deletions ada/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1183,9 +1183,8 @@ def has_with_visibility(refd_unit=AnalysisUnit,

@langkit_property(return_type=Bool)
def has_visibility(other_entity=T.AdaNode.entity):
# If we found a synthetic type predicate object decl, it means we are
# inside the definition of the type. From there, check if we indeed
# have visibility on the synthetic object.
# We found a synthetic type predicate object decl, check if we are
# allowed to see it.
return other_entity.cast(SyntheticTypePredicateObjectDecl).then(
lambda sod: sod.is_referred_by(Self),
default_val=True
Expand Down Expand Up @@ -9178,11 +9177,9 @@ class SyntheticTypePredicateObjectDecl(BasicDecl):
def is_referred_by(origin=T.AdaNode):
"""
Return whether a synthetic type predicate object can be seen from the
given ``origin`` node. This already assumes that we are inside a type
definition (otherwise the env lookup would not have found the synthetic
object), but this can be used to know if the reference points to the
synthetic object or to the type itself. By default this will always be
the synthetic object, unless we are in an access type definition. This
given ``origin`` node. If we are outside the type definition, this will
always be the type itself. Otherwise this will always be the synthetic
object, unless we are in an access type definition. In particular, this
allows correctly resolving:

.. code:: ada
Expand All @@ -9195,7 +9192,14 @@ def is_referred_by(origin=T.AdaNode):
Here, the reference (1) points to the type, whereas (2) refers to the
synthetic object.
"""
return Not(origin.parent.parent.is_a(TypeAccessDef))
return And(
Not(origin.parent.parent.is_a(TypeAccessDef)),
Self.is_children_env(
Self.type_expr.cast(SyntheticTypeExpr)
.target_type.children_env,
origin.children_env
)
)


@synthetic
Expand Down
13 changes: 13 additions & 0 deletions testsuite/tests/name_resolution/record_self_access/test.adb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ procedure Test is
--% access_type.f_type_def.f_subtype_indication.p_designated_type_decl
--% node.f_default_expr.f_prefix.p_referenced_decl()
end record;

type A is record
B : Integer;
end record;

type B is new A;

procedure Assign (X : in out B; Y : B) is
begin
X.B := Y.B;
--% node.f_dest.f_suffix.p_referenced_decl()
--% node.f_expr.f_suffix.p_referenced_decl()
end Assign;
begin
null;
end Test;
Expand Down
9 changes: 9 additions & 0 deletions testsuite/tests/name_resolution/record_self_access/test.out
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ Result: <ConcreteTypeDecl ["T_2"] test.adb:10:4-16:15>

Eval 'node.f_default_expr.f_prefix.p_referenced_decl()'
Result: <SyntheticTypePredicateObjectDecl ["T_2"] test.adb:10:4-16:15>

Working on node <AssignStmt test.adb:26:7-26:18>
================================================

Eval 'node.f_dest.f_suffix.p_referenced_decl()'
Result: <ComponentDecl ["B"] test.adb:19:7-19:19>

Eval 'node.f_expr.f_suffix.p_referenced_decl()'
Result: <ComponentDecl ["B"] test.adb:19:7-19:19>

0 comments on commit 1dddaf7

Please sign in to comment.