The semantics of the return statement includes an implicit conversion of
the value to the return type of the funcction. This conversion, as
elsewhere, entails a predicate check if the return type has a predicate
aspect.

We do not apply the check to a case expression because in the context of
a return statement it will be expanded into a series of return
statements, each of which will receive a predicate check.

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

2018-09-26  Ed Schonberg  <schonb...@adacore.com>

gcc/ada/

        * sem_ch6.adb (Analyze_Function_Return): If the return type has
        a dynamic_predicate, apply a Predicate_Check to the expression,
        given that it is implicitly converted to the return type.
        Exclude case expressions from the check, because in this context
        the expression is expanded into individual return statements.

gcc/testsuite/

        * gnat.dg/predicate3.adb, gnat.dg/predicate3_pkg.ads: New
        testcase.
--- gcc/ada/sem_ch6.adb
+++ gcc/ada/sem_ch6.adb
@@ -1060,6 +1060,16 @@ package body Sem_Ch6 is
 
          Apply_Constraint_Check (Expr, R_Type);
 
+         --  The return value is converted to the return type of the function,
+         --  which implies a predicate check if the return type is predicated.
+         --  We do not apply the check to a case expression because it will
+         --  be expanded into a series of return statements, each of which
+         --  will receive a predicate check.
+
+         if Nkind (Expr) /= N_Case_Expression then
+            Apply_Predicate_Check (Expr, R_Type);
+         end if;
+
          --  Ada 2005 (AI-318-02): When the result type is an anonymous access
          --  type, apply an implicit conversion of the expression to that type
          --  to force appropriate static and run-time accessibility checks.

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/predicate3.adb
@@ -0,0 +1,39 @@
+--  { dg-do run }
+--  { dg-options "-gnata" }
+
+with Ada.Assertions, Ada.Text_IO;
+use  Ada.Assertions, Ada.Text_IO;
+
+with Predicate3_Pkg;
+use  Predicate3_Pkg;
+
+procedure Predicate3 is
+   Got_Assertion : Boolean := False;
+begin
+
+   begin
+      Put_Line (Good (C)'Image);
+   exception
+      when Assertion_Error =>
+         Got_Assertion := True;
+   end;
+
+   if not Got_Assertion then
+      raise Program_Error;
+   end if;
+
+   Got_Assertion := False;
+   declare
+      X: Priv;
+   begin
+      X := Wrong;
+   exception
+      when Assertion_Error =>
+         Got_Assertion := True;
+   end;
+
+   if not Got_Assertion then
+      raise Program_Error;
+   end if;
+
+end Predicate3;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/predicate3_pkg.ads
@@ -0,0 +1,22 @@
+package Predicate3_Pkg is
+ 
+   type Priv is private;
+   C: constant Priv;
+ 
+   function Test (X: Priv) return Boolean;
+   subtype Subt is Priv with Dynamic_Predicate => (Test (Subt));
+ 
+   function Wrong return Subt;
+   function Good (X: Subt) return Boolean;
+ 
+private
+ 
+   type Priv is new Integer;
+   C: constant Priv := -1;
+ 
+   function Test (X: Priv) return Boolean is (X > 0);
+ 
+   function Wrong return Subt is (-1);
+   function Good (X: Subt) return Boolean is (True);
+ 
+end Predicate3_Pkg;

Reply via email to