From 1e57bf475bf7651b30a5a3199bc669617c5004a6 Mon Sep 17 00:00:00 2001
From: Joseph Myers <joseph@codesourcery.com>
Date: Mon, 30 Mar 2009 02:25:37 +0100
Subject: [PATCH] re PR c/35235 (struct/union rvalue qualifiers must not
 propagate to members)

	PR c/35235
	* c-typeck.c (build_component_ref): Do not copy qualifiers from
	non-lvalue to component.

testsuite:
	* gcc.dg/c99-array-lval-8.c: New test.

From-SVN: r145271
---
 gcc/ChangeLog                           |  6 +++++
 gcc/c-typeck.c                          | 18 ++++++++++++---
 gcc/testsuite/ChangeLog                 |  5 +++++
 gcc/testsuite/gcc.dg/c99-array-lval-8.c | 30 +++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/c99-array-lval-8.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5f2d8ee77278..49bbb0f9d777 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2009-03-30  Joseph Myers  <joseph@codesourcery.com>
+
+	PR c/35235
+	* c-typeck.c (build_component_ref): Do not copy qualifiers from
+	non-lvalue to component.
+
 2009-03-29  Joseph Myers  <joseph@codesourcery.com>
 
 	PR preprocessor/34695
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 674220ca3b01..2559b1d92a8c 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -1904,6 +1904,7 @@ build_component_ref (tree datum, tree component)
   enum tree_code code = TREE_CODE (type);
   tree field = NULL;
   tree ref;
+  bool datum_lvalue = lvalue_p (datum);
 
   if (!objc_is_public (datum, component))
     return error_mark_node;
@@ -1936,19 +1937,30 @@ build_component_ref (tree datum, tree component)
 	  tree subdatum = TREE_VALUE (field);
 	  int quals;
 	  tree subtype;
+	  bool use_datum_quals;
 
 	  if (TREE_TYPE (subdatum) == error_mark_node)
 	    return error_mark_node;
 
+	  /* If this is an rvalue, it does not have qualifiers in C
+	     standard terms and we must avoid propagating such
+	     qualifiers down to a non-lvalue array that is then
+	     converted to a pointer.  */
+	  use_datum_quals = (datum_lvalue
+			     || TREE_CODE (TREE_TYPE (subdatum)) != ARRAY_TYPE);
+
 	  quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum)));
-	  quals |= TYPE_QUALS (TREE_TYPE (datum));
+	  if (use_datum_quals)
+	    quals |= TYPE_QUALS (TREE_TYPE (datum));
 	  subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals);
 
 	  ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
 			NULL_TREE);
-	  if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
+	  if (TREE_READONLY (subdatum)
+	      || (use_datum_quals && TREE_READONLY (datum)))
 	    TREE_READONLY (ref) = 1;
-	  if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
+	  if (TREE_THIS_VOLATILE (subdatum)
+	      || (use_datum_quals && TREE_THIS_VOLATILE (datum)))
 	    TREE_THIS_VOLATILE (ref) = 1;
 
 	  if (TREE_DEPRECATED (subdatum))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2b3a2165a577..23701aae2234 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-03-30  Joseph Myers  <joseph@codesourcery.com>
+
+	PR c/35235
+	* gcc.dg/c99-array-lval-8.c: New test.
+
 2009-03-29  Joseph Myers  <joseph@codesourcery.com>
 
 	PR preprocessor/34695
diff --git a/gcc/testsuite/gcc.dg/c99-array-lval-8.c b/gcc/testsuite/gcc.dg/c99-array-lval-8.c
new file mode 100644
index 000000000000..b5048b66a77b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c99-array-lval-8.c
@@ -0,0 +1,30 @@
+/* Test for non-lvalue arrays: test that qualifiers on non-lvalues
+   containing arrays do not remain when those arrays decay to
+   pointers.  PR 35235.  */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+int a;
+
+void
+f (void)
+{
+  const struct {
+    int a[1];
+  } s;
+  int *p1 = s.a; /* { dg-error "qualifiers" } */
+  int *p2 = (a ? s : s).a;
+  /* In this case, the qualifier is properly on the array element type
+     not on the rvalue structure and so is not discarded.  */
+  struct {
+    const int a[1];
+  } t;
+  int *p3 = t.a; /* { dg-error "qualifiers" } */
+  int *p4 = (a ? t : t).a; /* { dg-error "qualifiers" } */
+  /* The issue could also lead to code being wrongly accepted.  */
+  const struct {
+    int a[1][1];
+  } u;
+  const int (*p5)[1] = u.a;
+  const int (*p6)[1] = (a ? u : u).a; /* { dg-error "pointer" } */
+}
-- 
GitLab