Patchwork [Ada] Expansion of selected components that denote discriminants

login
register
mail settings
Submitter Arnaud Charlet
Date Aug. 3, 2011, 8:08 a.m.
Message ID <20110803080846.GA18186@adacore.com>
Download mbox | patch
Permalink /patch/108037/
State New
Headers show

Comments

Arnaud Charlet - Aug. 3, 2011, 8:08 a.m.
In general a selected component that denotes a discriminant can be replaced
with the corresponding discriminant value if it comes from a constrained type.
However if the discriminant is not static and is an expression with implicit
control, such as a short-circuit operation, copying the value may lead to
anomalies in code coverage.  Nevertheless, if the reference occurs within the
initialization code generated for an object declaration (typically because of
a change of representation in a derived type) the discriminant value must always
be copied from the type, because it may denote the still uninitialized component
of the object itself.

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

2011-08-03  Ed Schonberg  <schonberg@adacore.com>

	* exp_ch4.adb (Expand_N_Selected_Component): If the discriminant value
	is an integer literal it is always safe to replace the reference. In
	addition, if the reference appears in the generated code for an object
	declaration it is necessary to copy because otherwise the reference
	might be to the uninitilized value of the discriminant of the object
	itself.

Patch

Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb	(revision 177233)
+++ exp_ch4.adb	(working copy)
@@ -7594,6 +7594,18 @@ 
       --  unless the context of an assignment can provide size information.
       --  Don't we have a general routine that does this???
 
+      function Is_Subtype_Declaration return Boolean;
+      --  The replacement of a discriminant reference by its value is required
+      --  if this is part of the initialization of an temporary generated by
+      --  a change of representation. This shows up as the construction of a
+      --  discriminant constraint for a subtype declared at the same point as
+      --  the entity in the prefix of the selected component.
+      --  We recognize this case when the context of the reference is:
+      --
+      --   subtype ST is T(Obj.D);
+      --
+      --   The entity for Obj comes from source, and ST has the same sloc.
+
       -----------------------
       -- In_Left_Hand_Side --
       -----------------------
@@ -7607,6 +7619,21 @@ 
                      and then In_Left_Hand_Side (Parent (Comp)));
       end In_Left_Hand_Side;
 
+      -----------------------------
+      --  Is_Subtype_Declaration --
+      -----------------------------
+
+      function Is_Subtype_Declaration return Boolean is
+         Par : constant Node_Id := Parent (N);
+
+      begin
+         return
+           Nkind (Par) = N_Index_Or_Discriminant_Constraint
+             and then Nkind (Parent (Parent (Par))) = N_Subtype_Declaration
+             and then Comes_From_Source (Entity (Prefix (N)))
+             and then Sloc (Par) = Sloc (Entity (Prefix (N)));
+      end Is_Subtype_Declaration;
+
    --  Start of processing for Expand_N_Selected_Component
 
    begin
@@ -7730,9 +7757,19 @@ 
                   --  AND THEN was copied, causing problems for coverage
                   --  analysis tools).
 
+                  --  However, if the reference is part of the initialization
+                  --  code generated for an object declaration, we must use
+                  --  the discriminant value from the subtype constraint,
+                  --  because the selected component may be a reference to the
+                  --  object being initialized, whose discriminant is not yet
+                  --  set. This only happens in complex cases involving changes
+                  --  or representation.
+
                   if Disc = Entity (Selector_Name (N))
                     and then (Is_Entity_Name (Dval)
-                               or else Is_Static_Expression (Dval))
+                              or else Nkind (Dval) = N_Integer_Literal
+                              or else Is_Subtype_Declaration
+                              or else Is_Static_Expression (Dval))
                   then
                      --  Here we have the matching discriminant. Check for
                      --  the case of a discriminant of a component that is