[Ada] If-expressions and the capture of local values

Message ID 20130411122538.GA25371@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet April 11, 2013, 12:25 p.m.
The routine Safe_To_Capture_Values performs simple data-flow to determine
whether some characteristic of a variable (its value after assignment, or the
fact that an access value is non-null after a test) can be used downstream.
The value cannot be saved if the expression that determines that value appears
within a conditional construct. This patch recognizes the case where the
expression appears within the else_actions of a if_expression. In that case,
before the if-expression is expanded, those actions are not directly attached
to the AST.


   gnatmake -q -gnatwa -gnat12 test_null1.adb

must yield:


pragma Ada_2012;
with Text_IO; use Text_IO;
procedure Test_Null1 is
   type String_Access is access all String;
   type String_List is array (Positive range <>) of String_Access;

   type String_List_Access is access all String_List;

   procedure Dump  (L : String_List_Access) is
      if L  /= null then
         for J in L'Range loop
            Put_Line (L (J).all);
         end loop;
      end if;
   end Dump;

   procedure Append
     (L : in out String_List_Access;
      S :        String);

   procedure Append
     (L : in out String_List_Access;
      S :        String)
      Tmp : constant String_List_Access :=
        (if L = null then
            new String_List (1 .. 1)
            new String_List (1 .. L'Length + 1));

      Idx : Positive := 1;
      if L  /= null then
         for J in L'Range loop
            Tmp (Idx) := new String'(L (J).all);
            Idx := Idx + 1;
         end loop;
      end if;

      Tmp (Idx) := new String'(S);

      L := Tmp;
   end Append;

   L : String_List_Access := null;
   Append (L, "AAA");
   Dump (L);
end Test_Null1;

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

2013-04-11  Ed Schonberg  <schonberg@adacore.com>

	* sem_util.adb (Safe_To_Capture_Value): If the node belongs to
	an expression that has been attached to the else_actions of an
	if-expression, the capture is not safe.


Index: sem_util.adb
--- sem_util.adb	(revision 197744)
+++ sem_util.adb	(working copy)
@@ -12984,6 +12984,19 @@ 
                Desc := P;
                P    := Parent (P);
+               --  A special Ada 2012 case: the original node may be part
+               --  of the else_actions of a conditional expression, in which
+               --  case it might not have been expanded yet, and appears in
+               --  a non-syntactic list of actions. In that case it is clearly
+               --  not safe to save a value.
+               if No (P)
+                 and then Is_List_Member (Desc)
+                 and then No (Parent (List_Containing (Desc)))
+               then
+                  return False;
+               end if;
             end if;
          end loop;