https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124190
Bug ID: 124190
Summary: Max_Entry_Queue_Length => 0 aspect and restriction do
not work, in two different ways
Product: gcc
Version: 15.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: ada
Assignee: unassigned at gcc dot gnu.org
Reporter: liam at liampwll dot com
CC: dkm at gcc dot gnu.org
Target Milestone: ---
Created attachment 63739
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63739&action=edit
fix
There's two bugs here, both are demonstrated by the reproducer below. I came
across these when I was poking at entries for the last bug I reported. A patch
is attached and there's 3 more issues incoming that I came across while fixing
this. Some of the modified regions will be very close so I'll diff those
patches on top of this one and each other in the order I submit the issues.
First bug:
When applying Max_Entry_Queue_Length => 0 as an aspect GNAT acts as if there
were no restriction in place. This is incorrect as RM22 D.4(23/5) states that
"If a nonconfirming value is specified for Max_Entry_Queue_Length for an entry,
and an entry call or requeue would cause the queue for an entry to become
longer than the specified value, then Program_Error is raised at the point of
the call or requeue."
The confirming value is -1, not 0 (RM22 D.4(19/5)). Note that an entry call
that is immediately selected is never enqueued, see the second bug below for
confirmation of this from the RM.
Second bug:
When applying Max_Entry_Queue_Length => 0 as a restriction GNAT produces a
compile time error any time an entry call is seen. This is incorrect as:
1. RM22 D.7(19.1/2) states that "Max_Entry_Queue_Length defines the maximum
number of calls that are queued on an entry. Violation of this restriction
results in the raising of Program_Error at the point of the call or requeue."
2. RM22 9.5.3(8) states that "The named entry is checked to see if it is open;
if open, the entry call is said to be selected immediately ..."
3. RM22 9.5.3(12) states that "If the named entry is closed, the entry call is
added to an entry queue ..."
The combination of 2 and 3 implies that a call which is selected immediately is
not added to an entry queue, meaning that an entry call can be valid here and a
compile time error should not be produced. Even if an entry calls were always
enqueued, the RM requires a Program_Error to be raised here, it says nothing
about rejecting the program.
I suspect the latter issue exists due to the fact that GNAT has
Max_Entry_Queue_Depth which predates Max_Entry_Queue_Length, but this is now
defined as a synonym for Max_Entry_Queue_Length in the GNAT RM so its probably
fine to change its behaviour to align with the GNAT RM, although if an older
version defined it differently then any software relying on that might break.
The restriction Max_Entry_Queue_Length => -1 is rejected, however this is
correct as the RM says nothing about the use of -1 as a restriction, just as an
aspect.
Reproducer follows, uncomment the restriction for the second bug:
-- pragma Restrictions (Max_Entry_Queue_Length => 0);
with Ada.Text_IO; use Ada.Text_IO;
procedure Example is
protected Worker is
entry Do_Work
with Max_Entry_Queue_Length => 0;
procedure Unblock;
private
X : Boolean := False;
end Worker;
protected body Worker is
entry Do_Work when X is
begin
Put_Line ("Do_Work'Count = " & Do_Work'Count'Image);
delay 0.2; -- Busy loop also exhibits bug.
end Do_Work;
procedure Unblock is
begin
X := True;
end Unblock;
end Worker;
task type T;
task body T is
begin
Worker.Do_Work;
exception
when E : others =>
Put_Line ("Task died");
end T;
Tasks : array (1 .. 10) of T;
begin
delay 1.0;
Worker.Unblock;
Worker.Do_Work;
end Example;