Commit 4b17187f by Arnaud Charlet

[multiple changes]

2015-05-12  Ed Schonberg  <schonberg@adacore.com>

	* a-coormu.ads, a-coormu.adb: Add Indexing aspect, Reference_Type,
	and Reference_Control_Type to support element iterators over
	ordered multisets.
	* a-ciormu.ads, a-ciormu.adb: Ditto for
	indefinite_ordered_multisets.

2015-05-12  Hristian Kirtchev  <kirtchev@adacore.com>

	* exp_ch4.adb (Expand_N_Expression_With_Actions): Force
	the evaluation of the EWA expression.  Code cleanup.
	(Process_Transient_Object): Code cleanup.
	* exp_util.adb (Is_Aliased): Controlled transient objects found
	within EWA nodes are not aliased.
	(Is_Finalizable_Transient): Iterators are not finalizable transients.

From-SVN: r223076
parent 7858300e
2015-05-12 Ed Schonberg <schonberg@adacore.com>
* a-coormu.ads, a-coormu.adb: Add Indexing aspect, Reference_Type,
and Reference_Control_Type to support element iterators over
ordered multisets.
* a-ciormu.ads, a-ciormu.adb: Ditto for
indefinite_ordered_multisets.
2015-05-12 Hristian Kirtchev <kirtchev@adacore.com>
* exp_ch4.adb (Expand_N_Expression_With_Actions): Force
the evaluation of the EWA expression. Code cleanup.
(Process_Transient_Object): Code cleanup.
* exp_util.adb (Is_Aliased): Controlled transient objects found
within EWA nodes are not aliased.
(Is_Finalizable_Transient): Iterators are not finalizable transients.
2015-05-12 Robert Dewar <dewar@adacore.com> 2015-05-12 Robert Dewar <dewar@adacore.com>
* sem_prag.adb (Process_Atomic_Independent_Shared_Volatile): * sem_prag.adb (Process_Atomic_Independent_Shared_Volatile):
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- B o d y -- -- B o d y --
-- -- -- --
-- Copyright (C) 2004-2014, Free Software Foundation, Inc. -- -- Copyright (C) 2004-2015, Free Software Foundation, Inc. --
-- -- -- --
-- GNAT is free software; you can redistribute it and/or modify it under -- -- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- -- -- terms of the GNU General Public License as published by the Free Soft- --
...@@ -353,6 +353,45 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is ...@@ -353,6 +353,45 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
return Node.Color; return Node.Color;
end Color; end Color;
------------------------
-- Constant_Reference --
------------------------
function Constant_Reference
(Container : aliased Set;
Position : Cursor) return Constant_Reference_Type
is
begin
if Position.Container = null then
raise Constraint_Error with "Position cursor has no element";
end if;
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error with
"Position cursor designates wrong container";
end if;
pragma Assert (Vet (Position.Container.Tree, Position.Node),
"bad cursor in Constant_Reference");
-- Note: in predefined container units, the creation of a reference
-- increments the busy bit of the container, and its finalization
-- decrements it. In the absence of control machinery, this tampering
-- protection is missing.
declare
T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
pragma Unreferenced (T);
begin
return R : constant Constant_Reference_Type :=
(Element => Position.Node.Element,
Control => (Container => Container'Unrestricted_Access))
do
null;
end return;
end;
end Constant_Reference;
-------------- --------------
-- Contains -- -- Contains --
-------------- --------------
...@@ -1730,6 +1769,14 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is ...@@ -1730,6 +1769,14 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
raise Program_Error with "attempt to stream set cursor"; raise Program_Error with "attempt to stream set cursor";
end Read; end Read;
procedure Read
(Stream : not null access Root_Stream_Type'Class;
Item : out Constant_Reference_Type)
is
begin
raise Program_Error with "attempt to stream reference";
end Read;
--------------------- ---------------------
-- Replace_Element -- -- Replace_Element --
--------------------- ---------------------
...@@ -2055,4 +2102,11 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is ...@@ -2055,4 +2102,11 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
raise Program_Error with "attempt to stream set cursor"; raise Program_Error with "attempt to stream set cursor";
end Write; end Write;
procedure Write
(Stream : not null access Root_Stream_Type'Class;
Item : Constant_Reference_Type)
is
begin
raise Program_Error with "attempt to stream reference";
end Write;
end Ada.Containers.Indefinite_Ordered_Multisets; end Ada.Containers.Indefinite_Ordered_Multisets;
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- S p e c -- -- S p e c --
-- -- -- --
-- Copyright (C) 2004-2013, Free Software Foundation, Inc. -- -- Copyright (C) 2004-2015, Free Software Foundation, Inc. --
-- -- -- --
-- GNAT is free software; you can redistribute it and/or modify it under -- -- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- -- -- terms of the GNU General Public License as published by the Free Soft- --
...@@ -52,8 +52,9 @@ package Ada.Containers.Indefinite_Ordered_Multisets is ...@@ -52,8 +52,9 @@ package Ada.Containers.Indefinite_Ordered_Multisets is
-- otherwise, it returns True. -- otherwise, it returns True.
type Set is tagged private type Set is tagged private
with Default_Iterator => Iterate, with Constant_Indexing => Constant_Reference,
Iterator_Element => Element_Type; Default_Iterator => Iterate,
Iterator_Element => Element_Type;
pragma Preelaborable_Initialization (Set); pragma Preelaborable_Initialization (Set);
...@@ -128,6 +129,15 @@ package Ada.Containers.Indefinite_Ordered_Multisets is ...@@ -128,6 +129,15 @@ package Ada.Containers.Indefinite_Ordered_Multisets is
-- change the value of the element while Process is executing (to "tamper -- change the value of the element while Process is executing (to "tamper
-- with elements") will raise Program_Error. -- with elements") will raise Program_Error.
type Constant_Reference_Type
(Element : not null access constant Element_Type) is private
with Implicit_Dereference => Element;
function Constant_Reference
(Container : aliased Set;
Position : Cursor) return Constant_Reference_Type;
pragma Inline (Constant_Reference);
procedure Assign (Target : in out Set; Source : Set); procedure Assign (Target : in out Set; Source : Set);
function Copy (Source : Set) return Set; function Copy (Source : Set) return Set;
...@@ -469,6 +479,19 @@ private ...@@ -469,6 +479,19 @@ private
type Set_Access is access all Set; type Set_Access is access all Set;
for Set_Access'Storage_Size use 0; for Set_Access'Storage_Size use 0;
-- In all predefined libraries the following type is controlled, for proper
-- management of tampering checks. For performance reason we omit this
-- machinery for multisets, which are used in a number of our tools.
type Reference_Control_Type is record
Container : Set_Access;
end record;
type Constant_Reference_Type
(Element : not null access constant Element_Type) is record
Control : Reference_Control_Type;
end record;
type Cursor is record type Cursor is record
Container : Set_Access; Container : Set_Access;
Node : Node_Access; Node : Node_Access;
...@@ -500,6 +523,18 @@ private ...@@ -500,6 +523,18 @@ private
for Set'Read use Read; for Set'Read use Read;
procedure Read
(Stream : not null access Root_Stream_Type'Class;
Item : out Constant_Reference_Type);
for Constant_Reference_Type'Read use Read;
procedure Write
(Stream : not null access Root_Stream_Type'Class;
Item : Constant_Reference_Type);
for Constant_Reference_Type'Write use Write;
Empty_Set : constant Set := Empty_Set : constant Set :=
(Controlled with Tree => (First => null, (Controlled with Tree => (First => null,
Last => null, Last => null,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- B o d y -- -- B o d y --
-- -- -- --
-- Copyright (C) 2004-2014, Free Software Foundation, Inc. -- -- Copyright (C) 2004-2015, Free Software Foundation, Inc. --
-- -- -- --
-- GNAT is free software; you can redistribute it and/or modify it under -- -- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- -- -- terms of the GNU General Public License as published by the Free Soft- --
...@@ -321,6 +321,45 @@ package body Ada.Containers.Ordered_Multisets is ...@@ -321,6 +321,45 @@ package body Ada.Containers.Ordered_Multisets is
return Node.Color; return Node.Color;
end Color; end Color;
------------------------
-- Constant_Reference --
------------------------
function Constant_Reference
(Container : aliased Set;
Position : Cursor) return Constant_Reference_Type
is
begin
if Position.Container = null then
raise Constraint_Error with "Position cursor has no element";
end if;
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error with
"Position cursor designates wrong container";
end if;
pragma Assert (Vet (Position.Container.Tree, Position.Node),
"bad cursor in Constant_Reference");
-- Note: in predefined container units, the creation of a reference
-- increments the busy bit of the container, and its finalization
-- decrements it. In the absence of control machinery, this tampering
-- protection is missing.
declare
T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
pragma Unreferenced (T);
begin
return R : constant Constant_Reference_Type :=
(Element => Position.Node.Element'Unrestricted_Access,
Control => (Container => Container'Unrestricted_Access))
do
null;
end return;
end;
end Constant_Reference;
-------------- --------------
-- Contains -- -- Contains --
-------------- --------------
...@@ -1638,6 +1677,14 @@ package body Ada.Containers.Ordered_Multisets is ...@@ -1638,6 +1677,14 @@ package body Ada.Containers.Ordered_Multisets is
raise Program_Error with "attempt to stream set cursor"; raise Program_Error with "attempt to stream set cursor";
end Read; end Read;
procedure Read
(Stream : not null access Root_Stream_Type'Class;
Item : out Constant_Reference_Type)
is
begin
raise Program_Error with "attempt to stream reference";
end Read;
--------------------- ---------------------
-- Replace_Element -- -- Replace_Element --
--------------------- ---------------------
...@@ -1937,4 +1984,11 @@ package body Ada.Containers.Ordered_Multisets is ...@@ -1937,4 +1984,11 @@ package body Ada.Containers.Ordered_Multisets is
raise Program_Error with "attempt to stream set cursor"; raise Program_Error with "attempt to stream set cursor";
end Write; end Write;
procedure Write
(Stream : not null access Root_Stream_Type'Class;
Item : Constant_Reference_Type)
is
begin
raise Program_Error with "attempt to stream reference";
end Write;
end Ada.Containers.Ordered_Multisets; end Ada.Containers.Ordered_Multisets;
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- S p e c -- -- S p e c --
-- -- -- --
-- Copyright (C) 2004-2013, Free Software Foundation, Inc. -- -- Copyright (C) 2004-2015, Free Software Foundation, Inc. --
-- -- -- --
-- GNAT is free software; you can redistribute it and/or modify it under -- -- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- -- -- terms of the GNU General Public License as published by the Free Soft- --
...@@ -51,8 +51,9 @@ package Ada.Containers.Ordered_Multisets is ...@@ -51,8 +51,9 @@ package Ada.Containers.Ordered_Multisets is
-- otherwise, it returns True. -- otherwise, it returns True.
type Set is tagged private type Set is tagged private
with Default_Iterator => Iterate, with Constant_Indexing => Constant_Reference,
Iterator_Element => Element_Type; Default_Iterator => Iterate,
Iterator_Element => Element_Type;
pragma Preelaborable_Initialization (Set); pragma Preelaborable_Initialization (Set);
...@@ -127,6 +128,15 @@ package Ada.Containers.Ordered_Multisets is ...@@ -127,6 +128,15 @@ package Ada.Containers.Ordered_Multisets is
-- change the value of the element while Process is executing (to "tamper -- change the value of the element while Process is executing (to "tamper
-- with elements") will raise Program_Error. -- with elements") will raise Program_Error.
type Constant_Reference_Type
(Element : not null access constant Element_Type) is private
with Implicit_Dereference => Element;
function Constant_Reference
(Container : aliased Set;
Position : Cursor) return Constant_Reference_Type;
pragma Inline (Constant_Reference);
procedure Assign (Target : in out Set; Source : Set); procedure Assign (Target : in out Set; Source : Set);
function Copy (Source : Set) return Set; function Copy (Source : Set) return Set;
...@@ -473,6 +483,19 @@ private ...@@ -473,6 +483,19 @@ private
type Set_Access is access all Set; type Set_Access is access all Set;
for Set_Access'Storage_Size use 0; for Set_Access'Storage_Size use 0;
-- In all predefined libraries the following type is controlled, for proper
-- management of tampering checks. For performance reason we omit this
-- machinery for multisets, which are used in a number of our tools.
type Reference_Control_Type is record
Container : Set_Access;
end record;
type Constant_Reference_Type
(Element : not null access constant Element_Type) is record
Control : Reference_Control_Type;
end record;
type Cursor is record type Cursor is record
Container : Set_Access; Container : Set_Access;
Node : Node_Access; Node : Node_Access;
...@@ -504,6 +527,18 @@ private ...@@ -504,6 +527,18 @@ private
for Set'Read use Read; for Set'Read use Read;
procedure Read
(Stream : not null access Root_Stream_Type'Class;
Item : out Constant_Reference_Type);
for Constant_Reference_Type'Read use Read;
procedure Write
(Stream : not null access Root_Stream_Type'Class;
Item : Constant_Reference_Type);
for Constant_Reference_Type'Write use Write;
Empty_Set : constant Set := Empty_Set : constant Set :=
(Controlled with Tree => (First => null, (Controlled with Tree => (First => null,
Last => null, Last => null,
......
...@@ -4713,7 +4713,6 @@ package body Exp_Util is ...@@ -4713,7 +4713,6 @@ package body Exp_Util is
is is
Obj_Id : constant Entity_Id := Defining_Identifier (Decl); Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
Obj_Typ : constant Entity_Id := Base_Type (Etype (Obj_Id)); Obj_Typ : constant Entity_Id := Base_Type (Etype (Obj_Id));
Desig : Entity_Id := Obj_Typ;
function Initialized_By_Access (Trans_Id : Entity_Id) return Boolean; function Initialized_By_Access (Trans_Id : Entity_Id) return Boolean;
-- Determine whether transient object Trans_Id is initialized either -- Determine whether transient object Trans_Id is initialized either
...@@ -4916,31 +4915,61 @@ package body Exp_Util is ...@@ -4916,31 +4915,61 @@ package body Exp_Util is
-- Start of processing for Is_Aliased -- Start of processing for Is_Aliased
begin begin
Stmt := First_Stmt; -- A controlled transient object is not considered aliased when it
while Present (Stmt) loop -- appears inside an expression_with_actions node even when there are
if Nkind (Stmt) = N_Object_Declaration then -- explicit aliases of it:
Expr := Expression (Stmt);
-- do
if Present (Expr) -- Trans_Id : Ctrl_Typ ...; -- controlled transient object
and then Nkind (Expr) = N_Reference -- Alias : ... := Trans_Id; -- object is aliased
and then Nkind (Prefix (Expr)) = N_Identifier -- Val : constant Boolean :=
and then Entity (Prefix (Expr)) = Trans_Id -- ... Alias ...; -- aliasing ends
then -- <finalize Trans_Id> -- object safe to finalize
return True; -- in Val end;
end if;
-- Expansion ensures that all aliases are encapsulated in the actions
-- list and do not leak to the expression by forcing the evaluation
-- of the expression.
if Nkind (Rel_Node) = N_Expression_With_Actions then
return False;
elsif Nkind (Stmt) = N_Object_Renaming_Declaration then -- Otherwise examine the statements after the controlled transient
Ren_Obj := Find_Renamed_Object (Stmt); -- object and look for various forms of aliasing.
if Present (Ren_Obj) and then Ren_Obj = Trans_Id then else
return True; Stmt := First_Stmt;
while Present (Stmt) loop
if Nkind (Stmt) = N_Object_Declaration then
Expr := Expression (Stmt);
-- Aliasing of the form:
-- Obj : ... := Trans_Id'reference;
if Present (Expr)
and then Nkind (Expr) = N_Reference
and then Nkind (Prefix (Expr)) = N_Identifier
and then Entity (Prefix (Expr)) = Trans_Id
then
return True;
end if;
elsif Nkind (Stmt) = N_Object_Renaming_Declaration then
Ren_Obj := Find_Renamed_Object (Stmt);
-- Aliasing of the form:
-- Obj : ... renames ... Trans_Id ...;
if Present (Ren_Obj) and then Ren_Obj = Trans_Id then
return True;
end if;
end if; end if;
end if;
Next (Stmt); Next (Stmt);
end loop; end loop;
return False; return False;
end if;
end Is_Aliased; end Is_Aliased;
------------------ ------------------
...@@ -5041,6 +5070,10 @@ package body Exp_Util is ...@@ -5041,6 +5070,10 @@ package body Exp_Util is
return False; return False;
end Is_Iterated_Container; end Is_Iterated_Container;
-- Local variables
Desig : Entity_Id := Obj_Typ;
-- Start of processing for Is_Finalizable_Transient -- Start of processing for Is_Finalizable_Transient
begin begin
...@@ -5083,6 +5116,12 @@ package body Exp_Util is ...@@ -5083,6 +5116,12 @@ package body Exp_Util is
and then not Is_Tag_To_Class_Wide_Conversion (Obj_Id) and then not Is_Tag_To_Class_Wide_Conversion (Obj_Id)
-- Do not consider iterators because those are treated as normal
-- controlled objects and are processed by the usual finalization
-- machinery. This avoids the double finalization of an iterator.
and then not Is_Iterator (Desig)
-- Do not consider containers in the context of iterator loops. Such -- Do not consider containers in the context of iterator loops. Such
-- transient objects must exist for as long as the loop is around, -- transient objects must exist for as long as the loop is around,
-- otherwise any operation carried out by the iterator will fail. -- otherwise any operation carried out by the iterator will fail.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment