This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] fix bad handling of function returning controlled


Tested on x86-linux, committed on mainline.

When the expression for a bound contains a call to a function that returns
a value that needs to be finalized, finalization must take place before
the loop execution starts, but after the value for the bound itself is
computed. In some cases the previous scheme finalized the value too early,
leading to incorrect execution.
The fix consists in generating an explicit temporary for any bound that
might contain a function call.
Test case: Program must execute quietly.
--
$ gnatmake p
$ p
--
with Ada.Text_IO; with Typ; use Typ;
procedure P is
   Count : Natural := 0;
   type Arr is array (Integer range <>) of Integer;
   Thing : Arr := (1..Get_Value (Make_T (42)) => 11);
begin
   if Get_Value (Make_T (12)) /= 12 then raise Program_Error; end if;

   if Thing'Last /= 42 then raise Program_Error; end if;

   for J in 1 .. Get_Value (Make_T (23)) loop
      Count := Count + 1;
   end loop;

   if Count /= 23 then
      Ada.Text_IO.Put_Line ("FAILED Iterated" & Count'Img & " times");
   end if;
end P;
with Ada.Finalization;
package Typ is
   type T is new Ada.Finalization.Controlled with record
      Val : Natural := 1;
   end record;
   function Make_T (N : Natural) return T;
   function Get_Value (X : T) return Natural;
   procedure Finalize (X : in out T);
end Typ;
package body Typ is
   A_T : T;

   function Make_T (N : Natural) return T is
   begin
      A_T.Val := N; return A_T;
   end Make_T;

   function Get_Value (X : T) return Natural is
   begin
     return X.Val;
   end Get_Value;

   procedure Finalize (X : in out T) is begin X.Val := 0; end Finalize;
end Typ;

While working on these changes, also uncovered another issue:
The indexed component form can be an indexed component, a slice, a call,
the indexing of a parameterless call, or a call to an element of an entry
family. If the prefix is a selected component, it can be a call to a
protected operation. In that case the selector will be an overloadable
entity (function, procedure or entry). If the name of the selector is
overloaded in the corresponding protected type, the recorded entity can
be any of the those and the context will disambiguate, so it is incorrect
to assume that this is a call only if the selector is a function.
Test case:
Expected output: ' 17'
$ gnatmake overloaded_op
$ overloaded_op
--
with text_io; use text_io;
procedure Overloaded_Op is

  protected Buffer is
    procedure Get (x, y : in Integer);
    function Get (x : in Integer) return Integer;
    entry Extract;
    function Extract (x : integer) return Integer;
  private
    Buffer : Integer;
  end Buffer;

  protected body Buffer is
    procedure Get (x, y : in Integer) is begin null; end Get;

    function Get (x : in Integer) return Integer is begin return 17; end Get;

    entry Extract when true is begin null; end;

    function Extract (x : Integer) return Integer is
    begin
       return Buffer + 1;
    end;
  end Buffer;
  DATA : constant Integer := Buffer.Get(1);
begin
  put_line (integer'image (data)); Buffer.Get (5, 6); Buffer.Extract;
end Overloaded_Op;

This patch also changes the meaning of the restriction No_Streams in
a way that makes it far more useful. Instead of forbidding any
attempt to WITH the Ada.Streams package, this restriction now
forbids any attempt to create a stream object, either with an
object declaration, or with an allocator. So it is possible to
use packages that WITH Ada.Streams in the presence of this
restriction pragma as long as no actual stream objects are
created.

2004-11-18  Ed Schonberg  <schonberg@adacore.com>
	    Robert Dewar  <dewar@adacore.com>

	* exp_ch4.adb (Expand_N_Selected_Component): If the component is the
	discriminant of a constrained subtype, analyze the copy of the
	corresponding constraint, because in some cases it may be only
	partially analyzed.
	Removes long-lived ??? comments.

	* exp_ch7.adb (Establish_Transient_Scope): Remove complex code that
	handled controlled or secondary-stack expressions within the
	iteration_scheme of a loop.

	* sem_ch5.adb (Analyze_Iteration_Scheme): Build a block to evaluate
	bounds that may contain functions calls, to prevent memory leaks when
	the bound contains a call to a function that uses the secondary stack.
	(Check_Complex_Bounds): Subsidiary of Analyze_Iteration_Scheme, to
	generate temporaries for loop bounds that might contain function calls
	that require secondary stack and/or finalization actions.

	* sem_ch4.adb (Analyze_Indexed_Component_Form): If the prefix is a
	selected component and the selector is overloadable (not just a
	function) treat as function call, Analyze_Call will disambiguate if
	necessary.
	(Analyze_Selected_Component): Do not generate an actual subtype for the
	selected component if expansion is disabled. The actual subtype is only
	needed for constraint checks.
	(Analyze_Allocator): If restriction No_Streams is set, then do
	not permit objects to be declared of a stream type, or of a
	composite type containing a stream.

	* restrict.ads: Remove the a-stream entry from Unit_Array, since
	No_Streams no longer prohibits with'ing this package.

	* sem_ch3.adb (Build_Derived_Record_Type): If the parent type has
	discriminants, but the parent base has unknown discriminants, there is
	no discriminant constraint to inherit. Such a discrepancy can arise
	when the actual for a formal type with unknown discriminants is a
	similar private type whose full view has discriminants.
	(Analyze_Object_Declaration): If restriction No_Streams is set, then
	do not permit objects to be declared of a stream type, or of a
	composite type containing a stream.

Attachment: difs.8
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]