diff mbox series

[Ada] Premature evaluation of message string in Assert pragma

Message ID 20171014170811.GA123098@adacore.com
State New
Headers show
Series [Ada] Premature evaluation of message string in Assert pragma | expand

Commit Message

Pierre-Marie de Rodat Oct. 14, 2017, 5:08 p.m. UTC
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  <schonberg@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.
diff mbox series

Patch

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