From a1c2b86d847dd68625e9209c6a6bc73cfdf01bb7 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Thu, 22 Mar 2001 18:00:28 +0100
Subject: [PATCH] method.c (do_build_assign_ref): Don't use build_modify_expr
 for anonymous aggregates...

	* method.c (do_build_assign_ref): Don't use build_modify_expr for
	anonymous aggregates, since they don't have assignment operator
	method.
	* decl.c (fixup_anonymous_aggr): Disallow ctors, dtors and copy
	assignment operators for anonymous structure fields.

	* g++.old-deja/g++.other/anon8.C: New test.

From-SVN: r40746
---
 gcc/cp/ChangeLog                             |  8 ++++++
 gcc/cp/decl.c                                | 27 ++++++++++++++++++++
 gcc/cp/method.c                              |  6 ++++-
 gcc/testsuite/ChangeLog                      |  4 +++
 gcc/testsuite/g++.old-deja/g++.other/anon8.C | 22 ++++++++++++++++
 5 files changed, 66 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.old-deja/g++.other/anon8.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f1cdaa755bd7..d2c9217b29ea 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2001-03-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* method.c (do_build_assign_ref): Don't use build_modify_expr for
+	anonymous aggregates, since they don't have assignment operator
+	method.
+	* decl.c (fixup_anonymous_aggr): Disallow ctors, dtors and copy
+	assignment operators for anonymous structure fields.
+
 2001-03-21  Jason Merrill  <jason@redhat.com>
 
 	* pt.c (instantiate_decl): Abort if we see a member constant
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 67aea126f48f..0a6296a47a0c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6815,6 +6815,33 @@ fixup_anonymous_aggr (t)
   /* ISO C++ 9.5.3.  Anonymous unions may not have function members.  */
   if (TYPE_METHODS (t))
     cp_error_at ("an anonymous union cannot have function members", t);
+
+  /* Anonymous aggregates cannot have fields with ctors, dtors or complex
+     assignment operators (because they cannot have these methods themselves).
+     For anonymous unions this is already checked because they are not allowed
+     in any union, otherwise we have to check it.  */
+  if (TREE_CODE (t) != UNION_TYPE)
+    {
+      tree field, type;
+
+      for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+	if (TREE_CODE (field) == FIELD_DECL)
+	  {
+	    type = TREE_TYPE (field);
+	    if (CLASS_TYPE_P (type))
+	      {
+	        if (TYPE_NEEDS_CONSTRUCTING (type))
+		  cp_error_at ("member %#D' with constructor not allowed in anonymous aggregate",
+			       field);
+		if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+		  cp_error_at ("member %#D' with destructor not allowed in anonymous aggregate",
+			       field);
+		if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
+		  cp_error_at ("member %#D' with copy assignment operator not allowed in anonymous aggregate",
+			       field);
+	      }
+	  }
+    }
 }
 
 /* Make sure that a declaration with no declarator is well-formed, i.e.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 5f917d5aabb6..c7e36132f57c 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -703,7 +703,11 @@ do_build_assign_ref (fndecl)
 	                build_qualified_type (TREE_TYPE (field), cvquals),
 	                init, field);
 
-	  finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
+	  if (DECL_NAME (field))
+	    finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
+	  else
+	    finish_expr_stmt (build (MODIFY_EXPR, TREE_TYPE (comp), comp,
+				     init));
 	}
     }
   finish_return_stmt (current_class_ref);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 57583fe4fc92..e75a1e01be48 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-03-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* g++.old-deja/g++.other/anon8.C: New test.
+
 2001-03-20  Philip Blundell  <philb@gnu.org>
 
 	* gcc.c-torture/compile/20010320-1.c: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/anon8.C b/gcc/testsuite/g++.old-deja/g++.other/anon8.C
new file mode 100644
index 000000000000..54d41b788c6a
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/anon8.C
@@ -0,0 +1,22 @@
+// Build don't link:
+
+struct B
+{
+  int a;
+  B & operator= (const B &);
+};
+
+struct A
+{
+  union {
+    int a;
+  };
+  B b;
+};
+
+A x;
+
+void foo (const A &y)
+{
+  x = y;
+}
-- 
GitLab