When compiling with -gnatc (or any mode that turns off the expansion phase),
the compiler gets an Assertion_Failure when attempting to retrieve the body
discriminal of a discriminant of a protected type. In the absence of expansion,
a concurrent record type is not created, so this possibility has to be
accounted for when retrieving body discriminals.

The following test must compile quietly with -gnatc:

procedure Requeue_Bug is

   type Boolean_Array is array (Positive range <>) of Boolean;

   protected type Protected_Type (Length : Positive) is
      entry Wait (Positive range 1 .. Length) (New_State : in Boolean);
      entry Wait_Next (New_State : in Boolean);
   private
      Available : Boolean_Array (1 .. Length) := (others => False);
   end Protected_Type;

   protected body Protected_Type is

      entry Wait
        (for J in Positive range 1 .. Length) (New_State : in Boolean)
           when Available (J)
      is
      begin
         null;
      end Wait;

      entry Wait_Next (New_State : in Boolean) when True is
      begin
         for J in 1 .. Length loop
            if not Available (J) then
               requeue Wait (J);
            end if;
         end loop;
      end Wait_Next;

   end Protected_Type;

begin
   null;
end Requeue_Bug;

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

2011-08-31  Gary Dismukes  <dismu...@adacore.com>

        * sem_util.adb (Find_Body_Discriminal): Test whether the scope of the
        spec discriminant is already a concurrent type, in which case just use
        it, otherwise fetch the Corresponding_Concurrent_Type as before.

Index: sem_util.adb
===================================================================
--- sem_util.adb        (revision 178355)
+++ sem_util.adb        (working copy)
@@ -3701,13 +3701,22 @@
    function Find_Body_Discriminal
      (Spec_Discriminant : Entity_Id) return Entity_Id
    is
-      pragma Assert (Is_Concurrent_Record_Type (Scope (Spec_Discriminant)));
-
-      Tsk  : constant Entity_Id :=
-               Corresponding_Concurrent_Type (Scope (Spec_Discriminant));
+      Tsk  : Entity_Id;
       Disc : Entity_Id;
 
    begin
+      --  If expansion is suppressed, then the scope can be the concurrent type
+      --  itself rather than a corresponding concurrent record type.
+
+      if Is_Concurrent_Type (Scope (Spec_Discriminant)) then
+         Tsk := Scope (Spec_Discriminant);
+
+      else
+         pragma Assert (Is_Concurrent_Record_Type (Scope (Spec_Discriminant)));
+
+         Tsk := Corresponding_Concurrent_Type (Scope (Spec_Discriminant));
+      end if;
+
       --  Find discriminant of original concurrent type, and use its current
       --  discriminal, which is the renaming within the task/protected body.
 

Reply via email to