From a1c2b86d847dd68625e9209c6a6bc73cfdf01bb7 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek 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 f1cdaa755bd..d2c9217b29e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2001-03-22 Jakub Jelinek + + * 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 * pt.c (instantiate_decl): Abort if we see a member constant diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 67aea126f48..0a6296a47a0 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 5f917d5aabb..c7e36132f57 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 57583fe4fc9..e75a1e01be4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-03-22 Jakub Jelinek + + * g++.old-deja/g++.other/anon8.C: New test. + 2001-03-20 Philip Blundell * 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 00000000000..54d41b788c6 --- /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; +}