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.
Executing: gnatmake -q -gnatwa -gnat12 test_null1.adb test_null1 must yield: AAA --- 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 begin 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) is Tmp : constant String_List_Access := (if L = null then new String_List (1 .. 1) else new String_List (1 .. L'Length + 1)); Idx : Positive := 1; begin 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; begin Append (L, "AAA"); Dump (L); end Test_Null1; Tested on x86_64-pc-linux-gnu, committed on trunk 2013-04-11 Ed Schonberg <schonb...@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 @@ else 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; end;