Patchwork [Ada] lift arbitrary limitation on external constants

login
register
mail settings
Submitter Eric Botcazou
Date Sept. 19, 2010, 1:05 p.m.
Message ID <201009191505.52561.ebotcazou@adacore.com>
Download mbox | patch
Permalink /patch/65158/
State New
Headers show

Comments

Eric Botcazou - Sept. 19, 2010, 1:05 p.m.
Gigi looks into the defining expression of external constants, except for two 
cases:

      /* If we have an external constant that we are not defining, get the
         expression that is was defined to represent.  We may throw that
         expression away later if it is not a constant.  Do not retrieve the
         expression if it is an aggregate or allocator, because in complex
         instantiation contexts it may not be expanded  */
      if (!definition
          && Present (Expression (Declaration_Node (gnat_entity)))
          && !No_Initialization (Declaration_Node (gnat_entity))
          && (Nkind (Expression (Declaration_Node (gnat_entity)))
              != N_Aggregate)
          && (Nkind (Expression (Declaration_Node (gnat_entity)))
              != N_Allocator))
        gnu_expr = gnat_to_gnu (Expression (Declaration_Node (gnat_entity)));

The first limitation is somewhat bogus: if you have a qualified aggregate, it 
is bypassed and we have tests that fail if gigi doesn't fold the qualified 
aggregate, because of additional elaboration code.  The attached patch lifts 
this limitation.

Tested on i586-suse-linux, applied on the mainline.


2010-09-19  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Constant>: Look into
	expressions for external constants that are aggregates.
	* gcc-interface/utils2.c (build_simple_component_ref): If the field
	is an inherited component in an extension, look through the extension.


2010-09-19  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/specs/constant1.ads: New test.
	* gnat.dg/specs/constant1_pkg.ads: New helper.

Patch

Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c	(revision 167578)
+++ gcc-interface/decl.c	(revision 167579)
@@ -421,17 +421,15 @@  gnat_to_gnu_entity (Entity_Id gnat_entit
 	}
 
       /* If we have an external constant that we are not defining, get the
-	 expression that is was defined to represent.  We may throw that
-	 expression away later if it is not a constant.  Do not retrieve the
-	 expression if it is an aggregate or allocator, because in complex
-	 instantiation contexts it may not be expanded  */
+	 expression that is was defined to represent.  We may throw it away
+	 later if it is not a constant.  But do not retrieve the expression
+	 if it is an allocator because the designated type might be dummy
+	 at this point.  */
       if (!definition
-	  && Present (Expression (Declaration_Node (gnat_entity)))
 	  && !No_Initialization (Declaration_Node (gnat_entity))
-	  && (Nkind (Expression (Declaration_Node (gnat_entity)))
-	      != N_Aggregate)
-	  && (Nkind (Expression (Declaration_Node (gnat_entity)))
-	      != N_Allocator))
+	  && Present (Expression (Declaration_Node (gnat_entity)))
+	  && Nkind (Expression (Declaration_Node (gnat_entity)))
+	     != N_Allocator)
 	gnu_expr = gnat_to_gnu (Expression (Declaration_Node (gnat_entity)));
 
       /* Ignore deferred constant definitions without address clause since
Index: gcc-interface/utils2.c
===================================================================
--- gcc-interface/utils2.c	(revision 167578)
+++ gcc-interface/utils2.c	(revision 167579)
@@ -1603,10 +1603,9 @@  build_simple_component_ref (tree record_
   if (!field)
     return NULL_TREE;
 
-  /* If this field is not in the specified record, see if we can find
-     something in the record whose original field is the same as this one. */
+  /* If this field is not in the specified record, see if we can find a field
+     in the specified record whose original field is the same as this one.  */
   if (DECL_CONTEXT (field) != record_type)
-    /* Check if there is a field with name COMPONENT in the record.  */
     {
       tree new_field;
 
@@ -1616,6 +1615,21 @@  build_simple_component_ref (tree record_
 	if (SAME_FIELD_P (field, new_field))
 	  break;
 
+      /* Next, see if we're looking for an inherited component in an extension.
+	 If so, look thru the extension directly.  */
+      if (!new_field
+	  && TREE_CODE (record_variable) == VIEW_CONVERT_EXPR
+	  && TYPE_ALIGN_OK (record_type)
+	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (record_variable, 0)))
+	     == RECORD_TYPE
+	  && TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (record_variable, 0))))
+	{
+	  ref = build_simple_component_ref (TREE_OPERAND (record_variable, 0),
+					    NULL_TREE, field, no_fold_p);
+	  if (ref)
+	    return ref;
+	}
+
       /* Next, loop thru DECL_INTERNAL_P components if we haven't found
          the component in the first search. Doing this search in 2 steps
          is required to avoiding hidden homonymous fields in the