diff mbox

[Ada] Improve removal of side effects in in-mode parameters

Message ID 20110802100242.GA16566@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Aug. 2, 2011, 10:02 a.m. UTC
This patch improves the removal of side effects in in-mode parameters
whose type is an access type. Required because the compiler was
considering side-effect free an in-mode parameter whose type is an
access type. This improvement is visible compiling the following
test with switch -gnatD:

procedure cutdown is
   type root is tagged record Msg : String (1 .. 123); end record;
   type ext is new root with record Len : natural; end record;

   type root_ref is access all Root'Class;

   function F (X : Root_Ref) return String is
     Result : String := X.Msg (1 .. Ext (X.all).Len);  --  [Test]
   begin
      return Result;
   end F;
begin
   null;
end;

The previous expansion of line [Test] included:

[constraint_error when
 cutdown__ext!(x.all).len >= 1 and then (integer(cutdown__ext!(x.all).
   len) > 123)
 "range check failed"]
[subtype cutdown__f__T184b is integer range 1 .. cutdown__ext!(x.all).len]

... and the nex expansion is as follows:

R184b : constant natural := cutdown__ext!(x.all).len;
[constraint_error when
 R184b >= 1 and then (integer(R184b) > 123)
 "range check failed"]
[subtype cutdown__f__T185b is integer range 1 .. R184b]

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

2011-08-02  Javier Miranda  <miranda@adacore.com>

	* exp_util.adb (Safe_Prefixed_Reference): Do not consider safe an
	in-mode parameter whose type is an access type since it can be used to
	modify its designated object. Enforce code that handles as safe an
	access type that is not access-to-constant but it is the result of a
	previous removal of side-effects.
	(Remove_Side_Effects): Minor code reorganization of cases which require
	no action. Done to incorporate documentation on new cases uncovered
	working in this ticket: no action needed if this routine was invoked
	too early and the nodes are not yet decorated.
	* sem_res.adb (Resolve_Slice): Minor code cleanup replacling two calls
	to routine Remove_Side_Effects by calls to Force_Evaluation since they
	were issued with actuals that are implicitly provided by
	Force_Evaluation.
diff mbox

Patch

Index: exp_util.adb
===================================================================
--- exp_util.adb	(revision 177089)
+++ exp_util.adb	(working copy)
@@ -4616,22 +4616,20 @@ 
 
          --  If the prefix is of an access type that is not access-to-constant,
          --  then this construct is a variable reference, which means it is to
-         --  be considered to have side effects if Variable_Ref is set True
-         --  Exception is an access to an entity that is a constant or an
-         --  in-parameter which does not come from source, and is the result
-         --  of a previous removal of side-effects.
+         --  be considered to have side effects if Variable_Ref is set True.
 
          elsif Is_Access_Type (Etype (Prefix (N)))
            and then not Is_Access_Constant (Etype (Prefix (N)))
            and then Variable_Ref
          then
-            if not Is_Entity_Name (Prefix (N)) then
-               return False;
-            else
-               return Ekind (Entity (Prefix (N))) = E_Constant
-                 or else Ekind (Entity (Prefix (N))) = E_In_Parameter;
-            end if;
+            --  Exception is a prefix that is the result of a previous removal
+            --  of side-effects.
 
+            return Is_Entity_Name (Prefix (N))
+              and then not Comes_From_Source (Prefix (N))
+              and then Ekind (Entity (Prefix (N))) = E_Constant
+              and then Is_Internal_Name (Chars (Entity (Prefix (N))));
+
          --  If the prefix is an explicit dereference then this construct is a
          --  variable reference, which means it is to be considered to have
          --  side effects if Variable_Ref is True.
@@ -4945,11 +4943,25 @@ 
    --  Start of processing for Remove_Side_Effects
 
    begin
-      --  If we are side effect free already or expansion is disabled,
-      --  there is nothing to do.
+      --  Handle cases in which there is nothing to do
 
-      if Side_Effect_Free (Exp) or else not Expander_Active then
+      if not Expander_Active then
          return;
+
+      --  Cannot generate temporaries if the invocation to remove side effects
+      --  was issued too early and the type of the expression is not resolved
+      --  (this happens because routines Duplicate_Subexpr_XX implicitly invoke
+      --  Remove_Side_Effects).
+
+      elsif No (Exp_Type)
+        or else Ekind (Exp_Type) = E_Access_Attribute_Type
+      then
+         return;
+
+      --  No action needed for side-effect free expressions
+
+      elsif Side_Effect_Free (Exp) then
+         return;
       end if;
 
       --  All this must not have any checks
Index: sem_res.adb
===================================================================
--- sem_res.adb	(revision 177119)
+++ sem_res.adb	(working copy)
@@ -8631,8 +8631,8 @@ 
 
             --  Ensure that side effects in the bounds are properly handled
 
-            Remove_Side_Effects (Low_Bound  (Drange), Variable_Ref => True);
-            Remove_Side_Effects (High_Bound (Drange), Variable_Ref => True);
+            Force_Evaluation (Low_Bound (Drange));
+            Force_Evaluation (High_Bound (Drange));
 
             --  Do not apply the range check to nodes associated with the
             --  frontend expansion of the dispatch table. We first check