aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-08-26 11:10:57 -0400
committerJason Merrill <jason@gcc.gnu.org>2016-08-26 11:10:57 -0400
commitd0b0fbd9fce2f30a82558bf2308b3a7b56c2f364 (patch)
tree8b759d9ca7a0bbc18fbf82d0501f69c847a84582 /gcc
parent9729a5d5241257d07aa2a9c2fa6c3abbd73e25e5 (diff)
downloadgcc-d0b0fbd9fce2f30a82558bf2308b3a7b56c2f364.zip
gcc-d0b0fbd9fce2f30a82558bf2308b3a7b56c2f364.tar.gz
gcc-d0b0fbd9fce2f30a82558bf2308b3a7b56c2f364.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c18
-rw-r--r--gcc/cp/class.c32
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit12.C2
5 files changed, 40 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 812c8c1..e8e2e03 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
2016-08-15 Jason Merrill <jason@redhat.com>
+ 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 05f0431..024519d 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 20689e4..a4f3c6b 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 8a32f17..72a128d 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 5c14c01..912d507 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit12.C
@@ -15,3 +15,5 @@ int main()
{
A<int> a;
}
+
+// { dg-final { scan-assembler-not "_ZN1AIiEC1Ev" } }