https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124310

--- Comment #10 from Liam Powell <liam at liampwll dot com> ---
In my continued quest to understand 3.10.2 I have got many headaches and one
more program that GNAT should reject but doesn't. I don't think this is worth
its own issue as no one will ever accidentally run in to this and it is not a
regression. However it is worth documenting in case someone decides to rework
the accessibility checking code one day:


procedure Example is
   type Rec is record
      A : aliased Integer;
   end record;

   type Wrapper is record
      B : aliased Rec;
   end record;

   function F (R : aliased Rec) return access constant Integer
   is (R.A'Access);

   X : access constant Integer :=
     (declare
        W : constant Wrapper := (B => (A => 123));
      begin
        F (W.B));
begin
   null;
end Example;


RM25 below = Ada 2022 with Amendment 1

The first thing we need to know is the master of the function call of F:

RM25 4.4(9.5/5): The operative constituent of a declare expression is its
body_expression.

RM25 3.10.2(16.1/5): "In the above rules, the operative constituents of a name
or expression (see 4.4) are considered to be used in a given context if the
enclosing name or expression is used in that context."

This applies to all the following rules, basically we can ignore the declare
expression and act as if the function were called directly.

RM25 3.10.2(10.3/5): (defining the master of a function call) "If the result is
of an anonymous access type and is converted to a (named or anonymous) access
type, the master is determined following the rules given below for determining
the master of an object created by an allocator (even if the access result is
of an access-to-subprogram type);"

Note that this never says the object has to come from an allocator, we just
follow the rules for all anonymous access type conversions.

RM25 3.10.2(14/6): "... For an anonymous allocator whose type is that of a
stand-alone object of an anonymous access-to-object type, the accessibility
level is that of the declaration of the stand-alone object. ..."

The standalone object here is X, so we share the accessibility level of X,
therefore the master of the function call is master of X.


The second thing we need to know is the accessibility level of W:

RM25 7.6.1(3/6): The declare expression is a master as it's not part of an
enclosing expression or statement.

RM21 3.10.2(7/5): "An entity or view defined by a declaration and created as
part of its elaboration has the same accessibility level as the innermost
master of the declaration except in the cases of renaming and derived access
types described below. ..."

The accessibility level of W is that of the declare expression which is a
master and is deeper than the master of X.


Now that we have both those levels we can see where the program should be
rejected:

RM25 6.4.1(6.4/3): "In a function call, the accessibility level of the actual
object for each explicitly aliased parameter shall not be statically deeper
than the accessibility level of the master of the call (see 3.10.2)."

Reply via email to