An object declaration of a class-wide object with a tag-indeterminate initial
value is rewritten as a renaming of a dereference. The renaming must preserve
the kind of the object (constant or variable). Previous to this patch, the
compiler failed to reject a call to a primitive operation with an in-out
controlling formal, when the actual was a constant class-wide object.

Compiling main.adb in -gnat05 mode must yield:

    main.adb:16:04: actual for "I" must be a variable

with Element; use Element;
procedure Main
   Object : constant Element.I_Interface'Class := Element.T_Class'(null record);
end Main;
package Element is

   type I_Interface is interface;

   procedure Add (I : in out I_Interface) is abstract;

   function Create return I_Interface'Class;

   type T_Class is new I_Interface with null record;

   overriding procedure Add (I : in out T_Class) is null;
end Element;

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

2012-03-15  Ed Schonberg  <>

        * exp_ch3.adb (Expand_N_Object_Declaration): When rewriting the
        declaration of a class-wide object, retain the Ekind to prevent
        subsequent misuse of constants.

Index: exp_ch3.adb
--- exp_ch3.adb (revision 185390)
+++ exp_ch3.adb (working copy)
@@ -4829,10 +4829,12 @@
                   --  object renaming declaration ---because these identifiers
                   --  were previously added by Enter_Name to the current scope.
                   --  We must preserve the homonym chain of the source entity
-                  --  as well.
+                  --  as well. We must also preserve the kind of the entity,
+                  --  which may be a constant.
                   Set_Chars (Defining_Identifier (N), Chars (Def_Id));
                   Set_Homonym (Defining_Identifier (N), Homonym (Def_Id));
+                  Set_Ekind (Defining_Identifier (N), Ekind (Def_Id));
                   Exchange_Entities (Defining_Identifier (N), Def_Id);
             end if;

Reply via email to