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 <[email protected]>
* 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).
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);