RM 11.4.2 stipulates that the optional string argument in an Assert pragma is
evaluated only if the assertion fails and the string is incorporated into the
raise statement. Previous to this patch the string expression was evaluated
unconditionally, leading to unwanted side effects if its evaluation only
made sense in case of failure of the assertion.

Executing:

   gnatmake -gnata -gnatws -q main
   main

must yield:

   Assert succeeds

   raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : P should be null, got A_STRING

---
with Text_IO; use Text_IO;
procedure Main is
  P : access String;
  X : Integer;
  function Zero return Integer is begin return 0; end;

begin
  X := Zero;
  pragma Assert (P = null, "P should be null, got " & P.all);
  Put_Line ("Assert succeeds");

  if X = 0 then
      P := new String'("A_STRING");
   end if;

  pragma Assert (P = null, "P should be null, got " & P.all);
end Main;

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

2017-10-14  Ed Schonberg  <schonb...@adacore.com>

        * sem_prag.adb (Analyze_Pragma, case Check): Defer evaluation of the
        optional string in an Assert pragma until the expansion of the pragma
        has rewritten it as a conditional statement, so that the string
        argument is only evaluaed if the assertion fails. This is mandated by
        RM 11.4.2.

Index: sem_prag.adb
===================================================================
--- sem_prag.adb        (revision 253754)
+++ sem_prag.adb        (working copy)
@@ -13249,16 +13249,18 @@
                --  If checks are not on we don't want any expansion (since
                --  such expansion would not get properly deleted) but
                --  we do want to analyze (to get proper references).
-               --  The Preanalyze_And_Resolve routine does just what we want
+               --  The Preanalyze_And_Resolve routine does just what we want.
+               --  Ditto if pragma is active, because it will be rewritten
+               --  as an if-statement whose analysis will complete analysis
+               --  and expansion of the string message. This makes a
+               --  difference in the unusual case where the expression for
+               --  the string may have a side effect, such as raising an
+               --  exception. This is mandated by RM 11.4.2, which specifies
+               --  that the string expression is only evaluated if the
+               --  check fails and Assertion_Error is to be raised.
 
-               if Is_Ignored (N) then
-                  Preanalyze_And_Resolve (Str, Standard_String);
+               Preanalyze_And_Resolve (Str, Standard_String);
 
-                  --  Otherwise we need a proper analysis and expansion
-
-               else
-                  Analyze_And_Resolve (Str, Standard_String);
-               end if;
             end if;
 
             --  Now you might think we could just do the same with the Boolean

Reply via email to