From 9efe5fbde1e89eab9d4f55838c8a641060b97abb Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Wed, 8 Oct 2014 10:15:06 -0400
Subject: [PATCH] call.c (call_copy_ctor): New.

	* call.c (call_copy_ctor): New.
	(build_over_call): Use it to avoid infinite recursion on invalid code.

From-SVN: r216005
---
 gcc/cp/ChangeLog                          |  5 ++++
 gcc/cp/call.c                             | 29 +++++++++++++++++++++++
 gcc/testsuite/g++.dg/overload/ellipsis3.C |  9 +++++++
 3 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/overload/ellipsis3.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 77a825e86f87..c70de7e22ed1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2014-10-08  Jason Merrill  <jason@redhat.com>
+
+	* call.c (call_copy_ctor): New.
+	(build_over_call): Use it to avoid infinite recursion on invalid code.
+
 2014-10-07  Jason Merrill  <jason@redhat.com>
 
 	* tree.c (cp_tree_equal) [TRAIT_EXPR]: Use cp_tree_equal for type2.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 347070c9c965..76d8eabf33f1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6896,6 +6896,25 @@ mark_versions_used (tree fn)
     }
 }
 
+/* Build a call to "the copy constructor" for the type of A, even if it
+   wouldn't be selected by normal overload resolution.  Used for
+   diagnostics.  */
+
+static tree
+call_copy_ctor (tree a, tsubst_flags_t complain)
+{
+  tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (a));
+  tree binfo = TYPE_BINFO (ctype);
+  tree copy = get_copy_ctor (ctype, complain);
+  copy = build_baselink (binfo, binfo, copy, NULL_TREE);
+  tree ob = build_dummy_object (ctype);
+  vec<tree, va_gc>* args = make_tree_vector_single (a);
+  tree r = build_new_method_call (ob, copy, &args, NULL_TREE,
+				  LOOKUP_NORMAL, NULL, complain);
+  release_tree_vector (args);
+  return r;
+}
+
 /* Subroutine of the various build_*_call functions.  Overload resolution
    has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
    ARGS is a TREE_LIST of the unconverted arguments to the call.  FLAGS is a
@@ -7234,6 +7253,16 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       if (magic_varargs_p (fn))
 	/* Do no conversions for magic varargs.  */
 	a = mark_type_use (a);
+      else if (DECL_CONSTRUCTOR_P (fn)
+	       && same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (fn),
+							     TREE_TYPE (a)))
+	{
+	  /* Avoid infinite recursion trying to call A(...).  */
+	  if (complain & tf_error)
+	    /* Try to call the actual copy constructor for a good error.  */
+	    call_copy_ctor (a, complain);
+	  return error_mark_node;
+	}
       else
 	a = convert_arg_to_ellipsis (a, complain);
       argarray[j++] = a;
diff --git a/gcc/testsuite/g++.dg/overload/ellipsis3.C b/gcc/testsuite/g++.dg/overload/ellipsis3.C
new file mode 100644
index 000000000000..e7d34d6df43a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/ellipsis3.C
@@ -0,0 +1,9 @@
+struct A {
+  A(...);
+};
+
+int main()
+{
+  volatile A a;
+  volatile A a2(a);		// { dg-error "volatile" }
+}
-- 
GitLab