[Ada] Crash on expression function and tagged types
authorEd Schonberg <schonberg@adacore.com>
Tue, 21 Aug 2018 14:49:42 +0000 (14:49 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Tue, 21 Aug 2018 14:49:42 +0000 (14:49 +0000)
This patch fixes a compiler abort on an expression function whose
expression includes tagged types that have not been frozen before the
generated body of the function is analyzed, even though that body is
inserted at the end of the current declarative part.

2018-08-21  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

* sem_ch6.adb (Analyze_Subprogram_Body_Helper, Mask_Type):
Refine the handling of freezing types for expression functions
that are not completions, when analyzing the generated body for
the function: the body is inserted at the end of the enclosing
declarative part, and its analysis may freeze types declared in
the same scope that have not been frozen yet.

gcc/testsuite/

* gnat.dg/expr_func7.adb, gnat.dg/expr_func7.ads: New testcase.

From-SVN: r263735

gcc/ada/ChangeLog
gcc/ada/sem_ch6.adb
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/expr_func7.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/expr_func7.ads [new file with mode: 0644]

index ca38083e42c774f7313522803e60ddd07f731723..503aa062230a225702428b73d6def35c9d7efb75 100644 (file)
@@ -1,3 +1,12 @@
+2018-08-21  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_ch6.adb (Analyze_Subprogram_Body_Helper, Mask_Type):
+       Refine the handling of freezing types for expression functions
+       that are not completions, when analyzing the generated body for
+       the function: the body is inserted at the end of the enclosing
+       declarative part, and its analysis may freeze types declared in
+       the same scope that have not been frozen yet.
+
 2018-08-21  Ed Schonberg  <schonberg@adacore.com>
 
        * sem_ch6.adb: Remove Freeze_Expr_Types.
index 5548c81c5574cf08613541903eb65522f3ed2700..3e0cae1d8861d374495e5a7c32108349ed25959f 100644 (file)
@@ -3145,8 +3145,12 @@ package body Sem_Ch6 is
                end if;
 
                if not Is_Frozen (Typ) then
-                  Set_Is_Frozen (Typ);
-                  Append_New_Elmt (Typ, Result);
+                  if Scope (Typ) /= Current_Scope then
+                     Set_Is_Frozen (Typ);
+                     Append_New_Elmt (Typ, Result);
+                  else
+                     Freeze_Before (N, Typ);
+                  end if;
                end if;
             end Mask_Type;
 
@@ -3636,28 +3640,28 @@ package body Sem_Ch6 is
          --  They are necessary in any case to insure order of elaboration
          --  in gigi.
 
-         if not Is_Frozen (Spec_Id)
+         if Nkind (N) = N_Subprogram_Body
+           and then Was_Expression_Function (N)
+           and then not Has_Completion (Spec_Id)
+           and then Serious_Errors_Detected = 0
            and then (Expander_Active
                       or else ASIS_Mode
-                      or else (Operating_Mode = Check_Semantics
-                                and then Serious_Errors_Detected = 0))
+                      or else Operating_Mode = Check_Semantics)
          then
             --  The body generated for an expression function that is not a
             --  completion is a freeze point neither for the profile nor for
             --  anything else. That's why, in order to prevent any freezing
             --  during analysis, we need to mask types declared outside the
-            --  expression that are not yet frozen.
+            --  expression (and in an outer scope) that are not yet frozen.
 
-            if Nkind (N) = N_Subprogram_Body
-              and then Was_Expression_Function (N)
-              and then not Has_Completion (Spec_Id)
-            then
-               Set_Is_Frozen (Spec_Id);
-               Mask_Types := Mask_Unfrozen_Types (Spec_Id);
-            else
-               Set_Has_Delayed_Freeze (Spec_Id);
-               Freeze_Before (N, Spec_Id);
-            end if;
+            Set_Is_Frozen (Spec_Id);
+            Mask_Types := Mask_Unfrozen_Types (Spec_Id);
+
+         elsif not Is_Frozen (Spec_Id)
+           and then Serious_Errors_Detected = 0
+         then
+            Set_Has_Delayed_Freeze (Spec_Id);
+            Freeze_Before (N, Spec_Id);
          end if;
       end if;
 
index 444f3e852ca8a11978887e7f0148f60b7a560e04..6a6e2267a94eadba2ad9bab62b048f6e9910032a 100644 (file)
@@ -1,3 +1,7 @@
+2018-08-21  Ed Schonberg  <schonberg@adacore.com>
+
+       * gnat.dg/expr_func7.adb, gnat.dg/expr_func7.ads: New testcase.
+
 2018-08-21  Ed Schonberg  <schonberg@adacore.com>
 
        * gnat.dg/expr_func6.adb, gnat.dg/expr_func6.ads: New testcase.
diff --git a/gcc/testsuite/gnat.dg/expr_func7.adb b/gcc/testsuite/gnat.dg/expr_func7.adb
new file mode 100644 (file)
index 0000000..048af62
--- /dev/null
@@ -0,0 +1,5 @@
+--  { dg-do compile }
+
+package body Expr_Func7 is
+   procedure Dummy is null;
+end Expr_Func7;
diff --git a/gcc/testsuite/gnat.dg/expr_func7.ads b/gcc/testsuite/gnat.dg/expr_func7.ads
new file mode 100644 (file)
index 0000000..47fc6f8
--- /dev/null
@@ -0,0 +1,20 @@
+package Expr_Func7 is
+
+   type Abstract_Food is tagged null record;
+   type Abstract_Food_Access is access Abstract_Food'Class;
+
+   type Fruit is new Abstract_Food with record
+      Worm : Boolean;
+   end record;
+
+   type Bananas is tagged record
+      Inside : Abstract_Food_Access;
+   end record;
+
+   function Has_Worm
+     (B : Bananas) return Boolean is (Fruit (B.Inside.all).Worm);
+
+   Cool : Bananas;
+
+   procedure Dummy;
+end Expr_Func7;