decl.c (gnat_to_gnu_entity): For a constant object whose type has self-referential...
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 2 Apr 2008 10:06:57 +0000 (10:06 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 2 Apr 2008 10:06:57 +0000 (10:06 +0000)
* decl.c (gnat_to_gnu_entity) <object>: For a constant object whose
type has self-referential size, get the size from the initializing
expression directly if it is also a constant whose nominal type
has self-referential size.

From-SVN: r133831

gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/specs/discr_record_constant.ads [new file with mode: 0644]

index c3e49b92727bf91991becd3b2a5b4e2766d3d714..f37efec39a9bc92276d806fab966967dc2f61172 100644 (file)
@@ -1,3 +1,10 @@
+2008-04-02  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * decl.c (gnat_to_gnu_entity) <object>: For a constant object whose
+       type has self-referential size, get the size from the initializing
+       expression directly if it is also a constant whose nominal type
+       has self-referential size.
+
 2008-04-01  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        PR ada/33688
index 6f92fac5428ead4462a4003dccb06bc5e2445049..ee9c1c58cdef92f46f4da648ec394d9d736ee077 100644 (file)
@@ -607,15 +607,34 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
           initializing expression, in which case we can get the size from
           that.  Note that the resulting size may still be a variable, so
           this may end up with an indirect allocation.  */
-
        if (No (Renamed_Object (gnat_entity))
            && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type)))
          {
            if (gnu_expr && kind == E_Constant)
-             gnu_size
-               = SUBSTITUTE_PLACEHOLDER_IN_EXPR
-                 (TYPE_SIZE (TREE_TYPE (gnu_expr)), gnu_expr);
-
+             {
+               tree size = TYPE_SIZE (TREE_TYPE (gnu_expr));
+               if (CONTAINS_PLACEHOLDER_P (size))
+                 {
+                   /* If the initializing expression is itself a constant,
+                      despite having a nominal type with self-referential
+                      size, we can get the size directly from it.  */
+                   if (TREE_CODE (gnu_expr) == COMPONENT_REF
+                       && TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))
+                          == RECORD_TYPE
+                       && TYPE_IS_PADDING_P
+                          (TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))
+                       && TREE_CODE (TREE_OPERAND (gnu_expr, 0)) == VAR_DECL
+                       && (TREE_READONLY (TREE_OPERAND (gnu_expr, 0))
+                           || DECL_READONLY_ONCE_ELAB
+                              (TREE_OPERAND (gnu_expr, 0))))
+                     gnu_size = DECL_SIZE (TREE_OPERAND (gnu_expr, 0));
+                   else
+                     gnu_size
+                       = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, gnu_expr);
+                 }
+               else
+                 gnu_size = size;
+             }
            /* We may have no GNU_EXPR because No_Initialization is
               set even though there's an Expression.  */
            else if (kind == E_Constant
index c7b5920e9adc64fcf335f0f5069eab9a9435d636..873e2b76705b1bea915c522b45199ad11cf6b834 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-02  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/specs/discr_record_constant.ads: New test.
+
 2008-04-02  Richard Guenther  <rguenther@suse.de>
 
        * gcc.dg/tree-ssa/vrp38.c: New testcase.
diff --git a/gcc/testsuite/gnat.dg/specs/discr_record_constant.ads b/gcc/testsuite/gnat.dg/specs/discr_record_constant.ads
new file mode 100644 (file)
index 0000000..f43b138
--- /dev/null
@@ -0,0 +1,22 @@
+-- { dg-do compile }
+
+pragma Restrictions (No_Implicit_Heap_Allocations);
+
+package Discr_Record_Constant is
+
+   type T (Big : Boolean := False) is record
+      case Big is
+         when True =>
+            Content : Integer;
+         when False =>
+            null;
+       end case;
+    end record;
+
+    D : constant T := (True, 0);
+
+    Var :          T := D;    --  OK, maximum size
+    Con : constant T := D;    --  Violation of restriction
+    Ter : constant T := Con;  --  Violation of restriction
+
+end Discr_Record_Constant;