diff mbox

[Ada] Freezing in expression function that is a completion.

Message ID 20170428133333.GA9075@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet April 28, 2017, 1:33 p.m. UTC
The expresion in an expression function that is a completion freezes. This
is implemented by first freezing the return type of the function, and then
traversing the analyzed expression and freezing explicitly all type references
within. If the expression includes a type conversion between access to
interface types we must also freeze the interface types themselves so that
dispatch table pointers are properly declared before the expression function.

The following must compile quietly:
---
with Gen;
package Small is
  type I1 is interface;
  type I2 is interface;

  type I1_Ptr is access all I1'Class;
  type I2_Ptr is access all I2'Class;

  type Reference (Data : access I2'Class) is null record;

  package Instance is new Gen (I1);

  function Get return Reference;
private
  function Get return Reference is              
    ((Data => I2_Ptr (I1_Ptr'(Instance.Get))));
end;
---
generic
  type Iface is interface;
package Gen is
  function Get return access Iface'Class;
end;
---
package body Gen is
  function Get return access Iface'Class is begin return null; end;
end;

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

2017-04-28  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch6.adb (Freeze_Type_Refs): For an interface conversion
	node between access types, freeze the designated type as well,
	so that dispatch table pointers are created in the proper scope,
	and not in the constructed body of the expression function.
diff mbox

Patch

Index: sem_ch6.adb
===================================================================
--- sem_ch6.adb	(revision 247338)
+++ sem_ch6.adb	(working copy)
@@ -3110,6 +3110,18 @@ 
                      end if;
                   end;
                end if;
+
+            --  Freezing an access type does not freeze the designated
+            --  type, but freezing conversions between access to interfaces
+            --  requires that the interface types themselves be frozen, so
+            --  that dispatch table entities are properly created.
+            --  Unclear whether a more general rule is needed ???
+
+            elsif Nkind (Node) = N_Type_Conversion
+              and then Is_Access_Type (Etype (Node))
+              and then Is_Interface (Designated_Type (Etype (Node)))
+            then
+               Freeze_Before (N, Designated_Type (Etype (Node)));
             end if;
 
             return OK;