diff mbox

[Ada] Infinite loop on nested instantiations with dynamic elaboration checks

Message ID 20141023102719.GA24954@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Oct. 23, 2014, 10:27 a.m. UTC
This patch fixes an infinite loop in GNAT when dynamic elaboration checks are
generated for an instantiation of a generic function whose type is obtained
from a formal package.

The following must compile quietly:

   gcc -c -gnatE main.adb

---
with Ada.Text_IO; use Ada.Text_IO;
with Optional_Values;
with Optional_Values_Map;
procedure Main is
   package Optional_Floats   is new Optional_Values (T => Float);
   package Optional_Integers is new Optional_Values (T => Integer);

   function Int_Of_Float (X : Float) return Integer is
   begin
      return Integer (X);
   end Int_Of_Float;

   function Map is new Optional_Values_Map
     (Input_Type       => Float,
      Output_Type      => Integer,
      Optional_Inputs  => Optional_Floats,
      Optional_Outputs => Optional_Integers,
      Map              => Int_Of_Float);

   Pi : constant := 3.1415;

   Optional_Three : constant Optional_Integers.Optional_Value_Type :=
     Map (Optional_Floats.Of_Value (Value => Pi));
begin
   if Optional_Integers.Has_Value (Optional_Three) then
      declare
         Three : constant Integer :=
           Optional_Integers.Get_Value (Optional_Three);
      begin
         Put_Line ("Result =" & Three'Img);
      end;
   end if;
end Main;
---
package body Optional_Values is
   function Of_Value (Value : T) return Optional_Value_Type is
     ((Optional => (Has_Value => True, Value => Value)));

   function Get_Value (Optional_Value : Optional_Value_Type) return T is
     (Optional_Value.Optional.Value);

end Optional_Values;
---
generic
   type T is private;
package Optional_Values is
   pragma Pure;
   type Optional_Value_Type is private;

   Null_Optional_Value : constant Optional_Value_Type;

   function Of_Value (Value : T) return Optional_Value_Type;

   function Has_Value (Optional_Value : Optional_Value_Type) return Boolean;

   function Get_Value (Optional_Value : Optional_Value_Type) return T
     with Pre => Has_Value (Optional_Value);

private
   type Internal_Type (Has_Value : Boolean := False) is record
      case Has_Value is
         when True =>
            Value : T;
         when False =>
            null;
      end case;
   end record;

   type Optional_Value_Type is record
      Optional : Internal_Type;
   end record;

   Null_Optional_Value : constant Optional_Value_Type
     := (Optional => (Has_Value => False));

   function Has_Value (Optional_Value : Optional_Value_Type) return Boolean is
     (Optional_Value.Optional.Has_Value);

end Optional_Values;
---
function Optional_Values_Map
  (Optional_Input : Optional_Inputs.Optional_Value_Type)
  return Optional_Outputs.Optional_Value_Type
is
   use Optional_Inputs;
begin
   if Has_Value (Optional_Input) then
      return Optional_Outputs.Of_Value (Map (Get_Value (Optional_Input)));
   end if;
   return Optional_Outputs.Null_Optional_Value;
end Optional_Values_Map;
---
with Optional_Values;
generic
   type Input_Type  is private;
   type Output_Type is private;
   with package Optional_Inputs  is new Optional_Values (T => Input_Type);
   with package Optional_Outputs is new Optional_Values (T => Output_Type);
   with function Map (Input : Input_Type) return Output_Type;
function Optional_Values_Map
  (Optional_Input : Optional_Inputs.Optional_Value_Type)
  return Optional_Outputs.Optional_Value_Type;

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

2014-10-23  Ed Schonberg  <schonberg@adacore.com>

	* sem_attr.adb (Analyze_Attribute): The prefix of attribute Elaborated
	does not require freezing, in particular if it denotes a generic
	function.
diff mbox

Patch

Index: sem_attr.adb
===================================================================
--- sem_attr.adb	(revision 216574)
+++ sem_attr.adb	(working copy)
@@ -11164,8 +11164,17 @@ 
       --  Normally the Freezing is done by Resolve but sometimes the Prefix
       --  is not resolved, in which case the freezing must be done now.
 
-      Freeze_Expression (P);
+      --  For an elaboration check on a subprogram, we do not freeze its type.
+      --  It may be declared in an unrelated scope, in particular in the case
+      --  of a generic function whose type may remain unelaborated.
 
+      if Attr_Id = Attribute_Elaborated then
+         null;
+
+      else
+         Freeze_Expression (P);
+      end if;
+
       --  Finally perform static evaluation on the attribute reference
 
       Analyze_Dimension (N);