Patchwork [Ada] Legality checks on access-to-object types

login
register
mail settings
Submitter Arnaud Charlet
Date Aug. 29, 2011, 10:06 a.m.
Message ID <20110829100625.GA21515@adacore.com>
Download mbox | patch
Permalink /patch/112009/
State New
Headers show

Comments

Arnaud Charlet - Aug. 29, 2011, 10:06 a.m.
Some checks on illegal uses of class-wide expressions do not apply to access_
to_subprograms. Use base type to determine whether an access subtype belongs
to the latter category.

The following must compile quietly in Ada205 mode:

package T is
   pragma Elaborate_Body;
end T;
---
with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Strings.Hash;

package body T is
   type C is tagged null record;

   type Getter is access function return C'Class;
   package Getter_Maps is new Ada.Containers.Indefinite_Hashed_Maps
      (Key_Type        => String,
       Element_Type    => Getter,
       Hash            => Ada.Strings.Hash,
       Equivalent_Keys => "=");
   use Getter_Maps;

   M : Getter_Maps.Map := Getter_Maps.Empty_Map;
   G : Getter;

   function My_Get return C'Class is
      D : C;
   begin
      return D;
   end My_Get;

begin
   M.Insert ("foo", My_Get'Access);

   G := My_Get'Access;
   M.Insert ("foo", G);
end T;

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-08-29  Ed Schonberg  <schonberg@adacore.com>

	* sem_res.adb (Resolve_Actuals): Use base type to determine whether an
	access subtype is access_to_subprogram, when applying checks for
	RM 3.10.2 (27).

Patch

Index: sem_res.adb
===================================================================
--- sem_res.adb	(revision 178155)
+++ sem_res.adb	(working copy)
@@ -3987,14 +3987,17 @@ 
                     ("& is not a dispatching operation of &!", A, Nam);
                end if;
 
+            --  Apply the checks described in 3.10.2(27): if the context is a
+            --  specific access-to-object, the actual cannot be class-wide.
+            --  Use base type to exclude access_to_subprogram cases.
+
             elsif Is_Access_Type (A_Typ)
               and then Is_Access_Type (F_Typ)
-              and then Ekind (F_Typ) /= E_Access_Subprogram_Type
-              and then Ekind (F_Typ) /= E_Anonymous_Access_Subprogram_Type
+              and then not Is_Access_Subprogram_Type (Base_Type (F_Typ))
               and then (Is_Class_Wide_Type (Designated_Type (A_Typ))
                          or else (Nkind (A) = N_Attribute_Reference
                                    and then
-                                     Is_Class_Wide_Type (Etype (Prefix (A)))))
+                                  Is_Class_Wide_Type (Etype (Prefix (A)))))
               and then not Is_Class_Wide_Type (Designated_Type (F_Typ))
               and then not Is_Controlling_Formal (F)
 
@@ -4008,9 +4011,7 @@ 
                Error_Msg_N
                  ("access to class-wide argument not allowed here!", A);
 
-               if Is_Subprogram (Nam)
-                 and then Comes_From_Source (Nam)
-               then
+               if Is_Subprogram (Nam) and then Comes_From_Source (Nam) then
                   Error_Msg_Node_2 := Designated_Type (F_Typ);
                   Error_Msg_NE
                     ("& is not a dispatching operation of &!", A, Nam);