aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/ChangeLog5
-rw-r--r--gcc/ada/gcc-interface/decl.c54
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gnat.dg/specs/lto3.ads10
-rw-r--r--gcc/testsuite/gnat.dg/specs/lto3_pkg1.adb24
-rw-r--r--gcc/testsuite/gnat.dg/specs/lto3_pkg1.ads26
-rw-r--r--gcc/testsuite/gnat.dg/specs/lto3_pkg2.adb7
-rw-r--r--gcc/testsuite/gnat.dg/specs/lto3_pkg2.ads11
8 files changed, 143 insertions, 0 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6a78278..2a2805a 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,10 @@
2010-05-08 Eric Botcazou <ebotcazou@adacore.com>
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Create variables for size
+ expressions of variant part of record types declared at library level.
+
+2010-05-08 Eric Botcazou <ebotcazou@adacore.com>
+
* gcc-interface/gigi.h (create_field_decl): Move PACKED parameter.
* gcc-interface/utils.c (create_field_decl): Move PACKED parameter.
(rest_of_record_type_compilation): Adjust call to create_field_decl.
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 3050475..b0334f2 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -4516,8 +4516,62 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
if (TREE_CODE (gnu_type) == RECORD_TYPE)
{
+ tree variant_part = get_variant_part (gnu_type);
tree ada_size = TYPE_ADA_SIZE (gnu_type);
+ if (variant_part)
+ {
+ tree union_type = TREE_TYPE (variant_part);
+ tree offset = DECL_FIELD_OFFSET (variant_part);
+
+ /* If the position of the variant part is constant, subtract
+ it from the size of the type of the parent to get the new
+ size. This manual CSE reduces the data size. */
+ if (TREE_CODE (offset) == INTEGER_CST)
+ {
+ tree bitpos = DECL_FIELD_BIT_OFFSET (variant_part);
+ TYPE_SIZE (union_type)
+ = size_binop (MINUS_EXPR, TYPE_SIZE (gnu_type),
+ bit_from_pos (offset, bitpos));
+ TYPE_SIZE_UNIT (union_type)
+ = size_binop (MINUS_EXPR, TYPE_SIZE_UNIT (gnu_type),
+ byte_from_pos (offset, bitpos));
+ }
+ else
+ {
+ TYPE_SIZE (union_type)
+ = elaborate_expression_1 (TYPE_SIZE (union_type),
+ gnat_entity,
+ get_identifier ("VSIZE"),
+ definition, false);
+
+ /* ??? For now, store the size as a multiple of the
+ alignment in bytes so that we can see the alignment
+ from the tree. */
+ TYPE_SIZE_UNIT (union_type)
+ = elaborate_expression_2 (TYPE_SIZE_UNIT (union_type),
+ gnat_entity,
+ get_identifier
+ ("VSIZE_A_UNIT"),
+ definition, false,
+ TYPE_ALIGN (union_type));
+
+ /* ??? For now, store the offset as a multiple of the
+ alignment in bytes so that we can see the alignment
+ from the tree. */
+ DECL_FIELD_OFFSET (variant_part)
+ = elaborate_expression_2 (offset,
+ gnat_entity,
+ get_identifier ("VOFFSET"),
+ definition, false,
+ DECL_OFFSET_ALIGN
+ (variant_part));
+ }
+
+ DECL_SIZE (variant_part) = TYPE_SIZE (union_type);
+ DECL_SIZE_UNIT (variant_part) = TYPE_SIZE_UNIT (union_type);
+ }
+
if (operand_equal_p (ada_size, size, 0))
ada_size = TYPE_SIZE (gnu_type);
else
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3435fdf..4a18a2b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2010-05-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/lto3.ads: New test.
+ * gnat.dg/specs/lto3_pkg1.ad[sb]: New helper.
+ * gnat.dg/specs/lto3_pkg2.ad[sb]: Likewise.
+
2010-05-08 Quentin Ochem <ochem@adacore.com>
* gnat.dg/sizetype3.ad[sb]: New test.
diff --git a/gcc/testsuite/gnat.dg/specs/lto3.ads b/gcc/testsuite/gnat.dg/specs/lto3.ads
new file mode 100644
index 0000000..815da5f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/lto3.ads
@@ -0,0 +1,10 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws -flto" }
+
+with Lto3_Pkg1;
+
+package Lto3 is
+
+ package P is new Lto3_Pkg1 (Id_T => Natural);
+
+end Lto3;
diff --git a/gcc/testsuite/gnat.dg/specs/lto3_pkg1.adb b/gcc/testsuite/gnat.dg/specs/lto3_pkg1.adb
new file mode 100644
index 0000000..34caa3c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/lto3_pkg1.adb
@@ -0,0 +1,24 @@
+package body Lto3_Pkg1 is
+
+ function Is_Fixed return Boolean is
+ begin
+ return True;
+ end Is_Fixed;
+
+ function Do_Item (I : Natural) return Variable_Data_Fixed_T is
+ It : Variable_Data_Fixed_T;
+ begin
+ return It;
+ end Do_Item;
+
+ My_Db : Db.T;
+
+ procedure Run is
+ Kitem : Variable_Data_Fixed_T;
+ I : Natural;
+ begin
+ Kitem := Db.Get (My_Db);
+ Kitem := Do_Item (I);
+ end Run;
+
+end Lto3_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/specs/lto3_pkg1.ads b/gcc/testsuite/gnat.dg/specs/lto3_pkg1.ads
new file mode 100644
index 0000000..5619b60
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/lto3_pkg1.ads
@@ -0,0 +1,26 @@
+-- { dg-excess-errors "no code generated" }
+
+with Lto3_Pkg2;
+
+generic
+ type Id_T is range <>;
+package Lto3_Pkg1 is
+
+ type Variable_Data_T (Fixed : Boolean := False) is
+ record
+ case Fixed is
+ when True =>
+ Length : Natural;
+ when False =>
+ null;
+ end case;
+ end record;
+
+ function Is_Fixed return Boolean;
+
+ type Variable_Data_Fixed_T is new Variable_Data_T (Is_Fixed);
+
+ package Db is new Lto3_Pkg2 (Id_T => Id_T,
+ Data_T => Variable_Data_Fixed_T);
+
+end Lto3_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/specs/lto3_pkg2.adb b/gcc/testsuite/gnat.dg/specs/lto3_pkg2.adb
new file mode 100644
index 0000000..d95fe60
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/lto3_pkg2.adb
@@ -0,0 +1,7 @@
+package body Lto3_Pkg2 is
+ function Get (X : T) return Data_T is
+ Result : Data_T;
+ begin
+ return Result;
+ end;
+end Lto3_Pkg2;
diff --git a/gcc/testsuite/gnat.dg/specs/lto3_pkg2.ads b/gcc/testsuite/gnat.dg/specs/lto3_pkg2.ads
new file mode 100644
index 0000000..52fdccb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/lto3_pkg2.ads
@@ -0,0 +1,11 @@
+-- { dg-excess-errors "no code generated" }
+
+generic
+ type Id_T is private;
+ type Data_T is private;
+package Lto3_Pkg2 is
+ type T is private;
+ function Get (X : T) return Data_T;
+private
+ type T is null record;
+end Lto3_Pkg2;