diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f1cdaa755bd73a4865fed168c671a67b82ac2dd2..d2c9217b29ea6ac11e12baab026344bc9b129a29 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 67aea126f48fa427542498dfdbe102a3701bc629..0a6296a47a0c44952a16e281aa19c10f10a315dc 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 5f917d5aabb6b7b5a8f85f14f8b37f6bc3bc822b..c7e36132f57c78db8473f424e1613473dee006b6 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 57583fe4fc92a27e37fbab44b0ce1dfa5e4d447c..e75a1e01be484fce828606ce5b1d4d3392f70a05 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 0000000000000000000000000000000000000000..54d41b788c6ad54bd8bc5f8b83c0f6321978e866 --- /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; +}