From d0b0fbd9fce2f30a82558bf2308b3a7b56c2f364 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 26 Aug 2016 11:10:57 -0400 Subject: [PATCH] Avoid calling a trivial default constructor. * class.c (default_ctor_p): New. (in_class_defaulted_default_constructor): Use it. (type_has_non_user_provided_default_constructor): Use it. * call.c (build_over_call): Handle trivial default constructor. * cp-tree.h: Declare default_ctor_p. From-SVN: r239783 --- gcc/cp/ChangeLog | 7 ++++++ gcc/cp/call.c | 18 ++++++++++---- gcc/cp/class.c | 32 +++++++++++++------------ gcc/cp/cp-tree.h | 1 + gcc/testsuite/g++.dg/cpp0x/explicit12.C | 2 ++ 5 files changed, 40 insertions(+), 20 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 812c8c10f66..e8e2e038b43 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2016-08-15 Jason Merrill + Avoid calling a trivial default constructor. + * class.c (default_ctor_p): New. + (in_class_defaulted_default_constructor): Use it. + (type_has_non_user_provided_default_constructor): Use it. + * call.c (build_over_call): Handle trivial default constructor. + * cp-tree.h: Declare default_ctor_p. + PR c++/57728 * pt.c (do_type_instantiation): Don't mess with non-user-provided member functions. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 05f0431b2a5..024519d3601 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7798,11 +7798,19 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) return val; } - else if (DECL_DESTRUCTOR_P (fn) - && trivial_fn_p (fn) - && !DECL_DELETED_FN (fn)) - return fold_convert (void_type_node, argarray[0]); - /* FIXME handle trivial default constructor, too. */ + else if (!DECL_DELETED_FN (fn) + && trivial_fn_p (fn)) + { + if (DECL_DESTRUCTOR_P (fn)) + return fold_convert (void_type_node, argarray[0]); + else if (default_ctor_p (fn)) + { + if (is_dummy_object (argarray[0])) + return force_target_expr (DECL_CONTEXT (fn), void_node, complain); + else + return cp_build_indirect_ref (argarray[0], RO_NULL, complain); + } + } /* For calls to a multi-versioned function, overload resolution returns the function with the highest target priority, that is, diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 20689e4dd06..a4f3c6b6aba 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -5133,8 +5133,17 @@ set_method_tm_attributes (tree t) } } -/* Returns true iff class T has a user-defined constructor other than - the default constructor. */ +/* Returns true if FN is a default constructor. */ + +bool +default_ctor_p (tree fn) +{ + return (DECL_CONSTRUCTOR_P (fn) + && sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn))); +} + +/* Returns true iff class T has a user-defined constructor that can be called + with more than zero arguments. */ bool type_has_user_nondefault_constructor (tree t) @@ -5163,23 +5172,16 @@ type_has_user_nondefault_constructor (tree t) tree in_class_defaulted_default_constructor (tree t) { - tree fns, args; - if (!TYPE_HAS_USER_CONSTRUCTOR (t)) return NULL_TREE; - for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns)) + for (tree fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); - if (DECL_DEFAULTED_IN_CLASS_P (fn)) - { - args = FUNCTION_FIRST_USER_PARMTYPE (fn); - while (args && TREE_PURPOSE (args)) - args = TREE_CHAIN (args); - if (!args || args == void_list_node) - return fn; - } + if (DECL_DEFAULTED_IN_CLASS_P (fn) + && default_ctor_p (fn)) + return fn; } return NULL_TREE; @@ -5268,8 +5270,8 @@ type_has_non_user_provided_default_constructor (tree t) { tree fn = OVL_CURRENT (fns); if (TREE_CODE (fn) == FUNCTION_DECL - && !user_provided_p (fn) - && sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn))) + && default_ctor_p (fn) + && !user_provided_p (fn)) return true; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8a32f179ecd..72a128d90dd 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5666,6 +5666,7 @@ extern void determine_key_method (tree); extern void check_for_override (tree, tree); extern void push_class_stack (void); extern void pop_class_stack (void); +extern bool default_ctor_p (tree); extern bool type_has_user_nondefault_constructor (tree); extern tree in_class_defaulted_default_constructor (tree); extern bool user_provided_p (tree); diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit12.C b/gcc/testsuite/g++.dg/cpp0x/explicit12.C index 5c14c019d88..912d507eed6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit12.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit12.C @@ -15,3 +15,5 @@ int main() { A a; } + +// { dg-final { scan-assembler-not "_ZN1AIiEC1Ev" } } -- 2.30.2