From b8bf6ad91b81efc271a5c91c9db34af15e2a483c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 8 Dec 2010 15:00:37 -0500 Subject: [PATCH] re PR c++/45822 (Qt 4.7.0 build fails) PR c++/45822 * cp-tree.h (LOOKUP_DEFAULTED): New. * call.c (add_function_candidate): Check it. * method.c (synthesized_method_walk): Set it. (do_build_copy_assign): Likewise. * init.c (perform_member_init): Likewise. (emit_mem_initializers): Likewise. From-SVN: r167602 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/call.c | 14 +++++++------- gcc/cp/cp-tree.h | 5 ++++- gcc/cp/init.c | 12 ++++++++++-- gcc/cp/method.c | 7 ++++--- gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/g++.dg/init/synth4.C | 18 ++++++++++++++++++ 7 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/init/synth4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b04f33a46d5d..e8329c1c4ad9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2010-12-08 Jason Merrill + PR c++/45822 + * cp-tree.h (LOOKUP_DEFAULTED): New. + * call.c (add_function_candidate): Check it. + * method.c (synthesized_method_walk): Set it. + (do_build_copy_assign): Likewise. + * init.c (perform_member_init): Likewise. + (emit_mem_initializers): Likewise. + PR c++/46736 * decl.c (cp_finish_decl): Complain about an implicitly deleted method defaulted outside the class. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d538cf2efc37..1e0b328a1b0a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1645,13 +1645,10 @@ add_function_candidate (struct z_candidate **candidates, else if (!sufficient_parms_p (parmnode)) viable = 0; - /* Kludge: When looking for a function from a subobject while generating - an implicit copy/move constructor/operator=, don't consider anything - that takes (a reference to) an unrelated type. See c++/44909. */ - else if (parmlist - && ((flags & LOOKUP_SPECULATIVE) - || (current_function_decl - && DECL_DEFAULTED_FN (current_function_decl)))) + /* When looking for a function from a subobject from an implicit + copy/move constructor/operator=, don't consider anything that takes (a + reference to) an unrelated type. See c++/44909 and core 1092. */ + else if (parmlist && (flags & LOOKUP_DEFAULTED)) { if (DECL_CONSTRUCTOR_P (fn)) i = 1; @@ -1667,6 +1664,9 @@ add_function_candidate (struct z_candidate **candidates, ctype)) viable = 0; } + + /* This only applies at the top level. */ + flags &= ~LOOKUP_DEFAULTED; } if (! viable) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index aba8dfddba96..03c02fc0933d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4227,9 +4227,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; another mechanism. Exiting early also avoids problems with trying to perform argument conversions when the class isn't complete yet. */ #define LOOKUP_SPECULATIVE (LOOKUP_LIST_ONLY << 1) +/* Used by calls from defaulted functions to limit the overload set to avoid + cycles trying to declare them (core issue 1092). */ +#define LOOKUP_DEFAULTED (LOOKUP_SPECULATIVE << 1) /* Used in calls to store_init_value to suppress its usual call to digest_init. */ -#define LOOKUP_ALREADY_DIGESTED (LOOKUP_SPECULATIVE << 1) +#define LOOKUP_ALREADY_DIGESTED (LOOKUP_DEFAULTED << 1) #define LOOKUP_NAMESPACES_ONLY(F) \ (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES)) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 9de8c9f61c3e..5a4f91cfb2b0 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -503,6 +503,9 @@ perform_member_init (tree member, tree init) } else { + int flags = LOOKUP_NORMAL; + if (DECL_DEFAULTED_FN (current_function_decl)) + flags |= LOOKUP_DEFAULTED; if (CP_TYPE_CONST_P (type) && init == NULL_TREE && !type_has_user_provided_default_constructor (type)) @@ -511,7 +514,7 @@ perform_member_init (tree member, tree init) permerror (DECL_SOURCE_LOCATION (current_function_decl), "uninitialized member %qD with % type %qT", member, type); - finish_expr_stmt (build_aggr_init (decl, init, 0, + finish_expr_stmt (build_aggr_init (decl, init, flags, tf_warning_or_error)); } } @@ -852,11 +855,16 @@ sort_mem_initializers (tree t, tree mem_inits) void emit_mem_initializers (tree mem_inits) { + int flags = LOOKUP_NORMAL; + /* We will already have issued an error message about the fact that the type is incomplete. */ if (!COMPLETE_TYPE_P (current_class_type)) return; + if (DECL_DEFAULTED_FN (current_function_decl)) + flags |= LOOKUP_DEFAULTED; + /* Sort the mem-initializers into the order in which the initializations should be performed. */ mem_inits = sort_mem_initializers (current_class_type, mem_inits); @@ -908,7 +916,7 @@ emit_mem_initializers (tree mem_inits) cp_build_indirect_ref (base_addr, RO_NULL, tf_warning_or_error), arguments, - LOOKUP_NORMAL, + flags, tf_warning_or_error); expand_cleanup_for_base (subobject, NULL_TREE); } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index dc723553cbb0..149910c2394e 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -583,6 +583,7 @@ do_build_copy_assign (tree fndecl) tree compound_stmt; bool move_p = move_fn_p (fndecl); bool trivial = trivial_fn_p (fndecl); + int flags = LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED; compound_stmt = begin_compound_stmt (0); parm = convert_from_reference (parm); @@ -622,7 +623,7 @@ do_build_copy_assign (tree fndecl) ansi_assopname (NOP_EXPR), &parmvec, base_binfo, - LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, + flags, tf_warning_or_error)); release_tree_vector (parmvec); } @@ -1175,12 +1176,12 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, if (diag) { - flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE; + flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; complain = tf_warning_or_error; } else { - flags = LOOKUP_PROTECT|LOOKUP_SPECULATIVE; + flags = LOOKUP_PROTECT|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; complain = tf_none; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f0aeca5c2109..e505dad28ed9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2010-12-08 Jason Merrill + PR c++/45822 + * g++.dg/init/synth4.C: New. + PR c++/46736 * g++.dg/cpp0x/defaulted21.C: New. diff --git a/gcc/testsuite/g++.dg/init/synth4.C b/gcc/testsuite/g++.dg/init/synth4.C new file mode 100644 index 000000000000..2b0b0b95a83b --- /dev/null +++ b/gcc/testsuite/g++.dg/init/synth4.C @@ -0,0 +1,18 @@ +// PR c++/45822 + +struct A +{ + A(int); +}; + +struct B +{ + B(A = 0); +}; + +struct C +{ + B b; +}; + +C c;