From 380271569e5ecfeba8ac253513b03936fa08a601 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Mon, 20 Jul 2009 19:39:22 +0200
Subject: [PATCH] tree-object-size.c (addr_object_size): Handle unions with
 array in it as last field of structs in __bos (...

	* tree-object-size.c (addr_object_size): Handle unions with
	array in it as last field of structs in __bos (, 1) as __bos (, 0).

	* gcc.dg/builtin-object-size-6.c: Adjust expected values.
	* gcc.dg/builtin-object-size-8.c: New test.
	* g++.dg/ext/builtin-object-size1.C: Adjust expected values.
	* g++.dg/ext/builtin-object-size2.C: Likewise.

From-SVN: r149825
---
 gcc/ChangeLog                                 |   3 +
 gcc/testsuite/ChangeLog                       |   5 +
 .../g++.dg/ext/builtin-object-size1.C         |   4 +-
 .../g++.dg/ext/builtin-object-size2.C         |   4 +-
 gcc/testsuite/gcc.dg/builtin-object-size-6.c  |   4 +-
 gcc/testsuite/gcc.dg/builtin-object-size-8.c  | 200 ++++++++++++++++++
 gcc/tree-object-size.c                        |  30 ++-
 7 files changed, 233 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-8.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c24dbe3c421c..6b658f3832e8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,8 @@
 2009-07-20  Jakub Jelinek  <jakub@redhat.com>
 
+	* tree-object-size.c (addr_object_size): Handle unions with
+	array in it as last field of structs in __bos (, 1) as __bos (, 0).
+
 	PR tree-optimization/40792
 	* tree.c (build_function_type_skip_args): Remove bogus assert.
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2e778c60c0c5..0a473c526db0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
 2009-07-20  Jakub Jelinek  <jakub@redhat.com>
 
+	* gcc.dg/builtin-object-size-6.c: Adjust expected values. 
+	* gcc.dg/builtin-object-size-8.c: New test. 
+	* g++.dg/ext/builtin-object-size1.C: Adjust expected values.
+	* g++.dg/ext/builtin-object-size2.C: Likewise.
+
 	PR tree-optimization/40792
 	* gcc.dg/pr40792.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/ext/builtin-object-size1.C b/gcc/testsuite/g++.dg/ext/builtin-object-size1.C
index 8baed692541f..8590a0bbebdc 100644
--- a/gcc/testsuite/g++.dg/ext/builtin-object-size1.C
+++ b/gcc/testsuite/g++.dg/ext/builtin-object-size1.C
@@ -399,11 +399,11 @@ test8 (union F *f)
 {
   if (__builtin_object_size (&f->d.c[3], 0) != (size_t) -1)
     abort ();
-  if (__builtin_object_size (&f->d.c[3], 1) != sizeof (f->d.c) - 3)
+  if (__builtin_object_size (&f->d.c[3], 1) != (size_t) -1)
     abort ();
   if (__builtin_object_size (&f->d.c[3], 2) != 0)
     abort ();
-  if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3)
+  if (__builtin_object_size (&f->d.c[3], 3) != 0)
     abort ();
 }
 
diff --git a/gcc/testsuite/g++.dg/ext/builtin-object-size2.C b/gcc/testsuite/g++.dg/ext/builtin-object-size2.C
index e1fe6de03306..d79b1b83310b 100644
--- a/gcc/testsuite/g++.dg/ext/builtin-object-size2.C
+++ b/gcc/testsuite/g++.dg/ext/builtin-object-size2.C
@@ -402,11 +402,11 @@ test8 (union F *f)
 {
   if (__builtin_object_size (&f->d.c[3], 0) != (size_t) -1)
     abort ();
-  if (__builtin_object_size (&f->d.c[3], 1) != sizeof (f->d.c) - 3)
+  if (__builtin_object_size (&f->d.c[3], 1) != (size_t) -1)
     abort ();
   if (__builtin_object_size (&f->d.c[3], 2) != 0)
     abort ();
-  if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3)
+  if (__builtin_object_size (&f->d.c[3], 3) != 0)
     abort ();
 }
 
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-6.c b/gcc/testsuite/gcc.dg/builtin-object-size-6.c
index 9a285dfb8835..c6887b854ace 100644
--- a/gcc/testsuite/gcc.dg/builtin-object-size-6.c
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-6.c
@@ -399,11 +399,11 @@ test8 (union F *f)
 {
   if (__builtin_object_size (&f->d.c[3], 0) != (size_t) -1)
     abort ();
-  if (__builtin_object_size (&f->d.c[3], 1) != sizeof (f->d.c) - 3)
+  if (__builtin_object_size (&f->d.c[3], 1) != (size_t) -1)
     abort ();
   if (__builtin_object_size (&f->d.c[3], 2) != 0)
     abort ();
-  if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3)
+  if (__builtin_object_size (&f->d.c[3], 3) != 0)
     abort ();
 }
 
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-8.c b/gcc/testsuite/gcc.dg/builtin-object-size-8.c
new file mode 100644
index 000000000000..f2d88f9d591e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-8.c
@@ -0,0 +1,200 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void *malloc (size_t);
+extern void free (void *);
+extern void abort (void);
+
+union A
+{
+  int a1;
+  char a2[3];
+};
+
+union B
+{
+  long long b1;
+  union A b2;
+};
+
+struct C
+{
+  int c1;
+  union A c2;
+};
+
+struct D
+{
+  int d1;
+  union B d2;
+};
+
+union E
+{
+  struct C e1;
+  char e2[3];
+};
+
+union F
+{
+  int f1;
+  struct D f2;
+};
+
+struct G
+{
+  union A g1;
+  char g2;
+};
+
+struct H
+{
+  int h1;
+  union E h2;
+};
+
+#define T(X, S0, S1) \
+  if (__builtin_object_size (X, 0) != (S0))	\
+    abort ();					\
+  if (__builtin_object_size (X, 1) != (S1))	\
+    abort ();					\
+  if (__builtin_object_size (X, 2) != (S0))	\
+    abort ();					\
+  if (__builtin_object_size (X, 3) != (S1))	\
+    abort ()
+#define TS(X, S0) T(&X, S0, sizeof (X))
+#define TA(X, S0, S1) \
+  T(X, S0, S1); T(&X[0], S0, S1); T(&X[1], (S0) - 1, (S1) - 1)
+#define TF(X, S0) TA(X, S0, S0)
+
+int
+main (void)
+{
+  size_t s, o, o2;
+
+  s = sizeof (union A);
+  o = 0;
+  union A *a1 = malloc (s);
+  union A *a2 = malloc (o + 212);
+  TS (a1->a1, s);
+  TF (a1->a2, s);
+  s = o + 212;
+  TS (a2->a1, s);
+  TF (a2->a2, s);
+  free (a2);
+  free (a1);
+
+  s = sizeof (union B);
+  o = 0;
+  union B *b1 = malloc (s);
+  union B *b2 = malloc (o + 212);
+  TS (b1->b1, s);
+  TS (b1->b2.a1, s);
+  TF (b1->b2.a2, s);
+  s = o + 212;
+  TS (b2->b1, s);
+  TS (b2->b2.a1, s);
+  TF (b2->b2.a2, s);
+  free (b2);
+  free (b1);
+
+  s = sizeof (struct C);
+  o = __builtin_offsetof (struct C, c2);
+  struct C *c1 = malloc (s);
+  struct C *c2 = malloc (o + 212);
+  TS (c1->c1, s);
+  TS (c1->c2.a1, s - o);
+  TF (c1->c2.a2, s - o);
+  s = o + 212;
+  TS (c2->c1, s);
+  TS (c2->c2.a1, s - o);
+  TF (c2->c2.a2, s - o);
+  free (c2);
+  free (c1);
+
+  s = sizeof (struct D);
+  o = __builtin_offsetof (struct D, d2);
+  struct D *d1 = malloc (s);
+  struct D *d2 = malloc (o + 212);
+  TS (d1->d1, s);
+  TS (d1->d2.b1, s - o);
+  TS (d1->d2.b2.a1, s - o);
+  TF (d1->d2.b2.a2, s - o);
+  s = o + 212;
+  TS (d2->d1, s);
+  TS (d2->d2.b1, s - o);
+  TS (d2->d2.b2.a1, s - o);
+  TF (d2->d2.b2.a2, s - o);
+  free (d2);
+  free (d1);
+
+  s = sizeof (union E);
+  o = __builtin_offsetof (union E, e1.c2);
+  union E *e1 = malloc (s);
+  union E *e2 = malloc (o + 212);
+  TS (e1->e1.c1, s);
+  TS (e1->e1.c2.a1, s - o);
+  TF (e1->e1.c2.a2, s - o);
+  TF (e1->e2, s);
+  s = o + 212;
+  TS (e2->e1.c1, s);
+  TS (e2->e1.c2.a1, s - o);
+  TF (e2->e1.c2.a2, s - o);
+  TF (e2->e2, s);
+  free (e2);
+  free (e1);
+
+  s = sizeof (union F);
+  o = __builtin_offsetof (union F, f2.d2);
+  union F *f1 = malloc (s);
+  union F *f2 = malloc (o + 212);
+  TS (f1->f1, s);
+  TS (f1->f2.d1, s);
+  TS (f1->f2.d2.b1, s - o);
+  TS (f1->f2.d2.b2.a1, s - o);
+  TF (f1->f2.d2.b2.a2, s - o);
+  s = o + 212;
+  TS (f2->f1, s);
+  TS (f2->f2.d1, s);
+  TS (f2->f2.d2.b1, s - o);
+  TS (f2->f2.d2.b2.a1, s - o);
+  TF (f2->f2.d2.b2.a2, s - o);
+  free (f2);
+  free (f1);
+
+  s = sizeof (struct G);
+  o = __builtin_offsetof (struct G, g2);
+  struct G *g1 = malloc (s);
+  struct G *g2 = malloc (o + 212);
+  TS (g1->g1.a1, s);
+  TA (g1->g1.a2, s, sizeof (g1->g1.a2));
+  TS (g1->g2, s - o);
+  s = o + 212;
+  TS (g2->g1.a1, s);
+  TA (g2->g1.a2, s, sizeof (g1->g1.a2));
+  TS (g2->g2, s - o);
+  free (g2);
+  free (g1);
+
+  s = sizeof (struct H);
+  o = __builtin_offsetof (struct H, h2);
+  o2 = __builtin_offsetof (struct H, h2.e1.c2);
+  struct H *h1 = malloc (s);
+  struct H *h2 = malloc (o2 + 212);
+  TS (h1->h1, s);
+  TS (h1->h2.e1.c1, s - o);
+  TS (h1->h2.e1.c2.a1, s - o2);
+  TA (h1->h2.e1.c2.a2, s - o2, sizeof (h1->h2.e1.c2.a2));
+  TF (h1->h2.e2, s - o);
+  s = o2 + 212;
+  TS (h2->h1, s);
+  TS (h2->h2.e1.c1, s - o);
+  TS (h2->h2.e1.c2.a1, s - o2);
+  TA (h2->h2.e1.c2.a2, s - o2, sizeof (h2->h2.e1.c2.a2));
+  TF (h2->h2.e2, s - o);
+  free (h2);
+  free (h1);
+
+  return 0;
+}
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 5c64b989d5ec..5b9fe38e96bb 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -217,7 +217,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
 		 && TREE_CODE (var) != IMAGPART_EXPR)
 	    var = TREE_OPERAND (var, 0);
 	  if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
-	      var = TREE_OPERAND (var, 0);
+	    var = TREE_OPERAND (var, 0);
 	  if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
 	      || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
 	      || (pt_var_size
@@ -262,8 +262,17 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
 			v = NULL_TREE;
 			break;
 		      }
-		    if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-			 == RECORD_TYPE)
+		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != UNION_TYPE
+			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != QUAL_UNION_TYPE)
+			break;
+		      else
+			v = TREE_OPERAND (v, 0);
+		    if (TREE_CODE (v) == COMPONENT_REF
+			&& TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			   == RECORD_TYPE)
 		      {
 			tree fld_chain = TREE_CHAIN (TREE_OPERAND (v, 1));
 			for (; fld_chain; fld_chain = TREE_CHAIN (fld_chain))
@@ -275,18 +284,17 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
 			    v = NULL_TREE;
 			    break;
 			  }
+			v = TREE_OPERAND (v, 0);
 		      }
-
-		    if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-			== RECORD_TYPE)
-		      v = TREE_OPERAND (v, 0);
-		    while (v && v != pt_var && TREE_CODE (v) == COMPONENT_REF)
-		      if (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE
-			  && TREE_CODE (TREE_TYPE (v)) != QUAL_UNION_TYPE)
+		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != UNION_TYPE
+			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != QUAL_UNION_TYPE)
 			break;
 		      else
 			v = TREE_OPERAND (v, 0);
-		    if (v && v != pt_var)
+		    if (v != pt_var)
 		      v = NULL_TREE;
 		    else
 		      v = pt_var;
-- 
GitLab