From: Jason Merrill Date: Fri, 25 Dec 2015 03:24:51 +0000 (-0500) Subject: re PR c++/69005 (infinite(?) recursion in template instantiations) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ee9661d435ccb883fe737e14813e24405942971c;p=gcc.git re PR c++/69005 (infinite(?) recursion in template instantiations) PR c++/69005 * call.c (add_template_candidate_real): Don't try to deduce X(X). From-SVN: r231952 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 02aa9b5c2c6..4c7e38452ec 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2015-12-24 Jason Merrill + + PR c++/69005 + * call.c (add_template_candidate_real): Don't try to deduce X(X). + 2015-12-22 Jason Merrill PR c++/66921 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index cdfa01ac63f..4f253563417 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3037,6 +3037,34 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, if (len < skip_without_in_chrg) return NULL; + if (DECL_CONSTRUCTOR_P (tmpl) && nargs == 2 + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (first_arg), + TREE_TYPE ((*arglist)[0]))) + { + /* 12.8/6 says, "A declaration of a constructor for a class X is + ill-formed if its first parameter is of type (optionally cv-qualified) + X and either there are no other parameters or else all other + parameters have default arguments. A member function template is never + instantiated to produce such a constructor signature." + + So if we're trying to copy an object of the containing class, don't + consider a template constructor that has a first parameter type that + is just a template parameter, as we would deduce a signature that we + would then reject in the code below. */ + if (tree firstparm = FUNCTION_FIRST_USER_PARMTYPE (tmpl)) + { + firstparm = TREE_VALUE (firstparm); + if (PACK_EXPANSION_P (firstparm)) + firstparm = PACK_EXPANSION_PATTERN (firstparm); + if (TREE_CODE (firstparm) == TEMPLATE_TYPE_PARM) + { + gcc_assert (!explicit_targs); + reason = invalid_copy_with_fn_template_rejection (); + goto fail; + } + } + } + nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0) + (len - skip_without_in_chrg)); args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg); @@ -3075,34 +3103,15 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, goto fail; } - /* In [class.copy]: - - A member function template is never instantiated to perform the - copy of a class object to an object of its class type. - - It's a little unclear what this means; the standard explicitly - does allow a template to be used to copy a class. For example, - in: - - struct A { - A(A&); - template A(const T&); - }; - const A f (); - void g () { A a (f ()); } - - the member template will be used to make the copy. The section - quoted above appears in the paragraph that forbids constructors - whose only parameter is (a possibly cv-qualified variant of) the - class type, and a logical interpretation is that the intent was - to forbid the instantiation of member templates which would then - have that form. */ if (DECL_CONSTRUCTOR_P (fn) && nargs == 2) { tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn); if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)), ctype)) { + /* We're trying to produce a constructor with a prohibited signature, + as discussed above; handle here any cases we didn't catch then, + such as X(X). */ reason = invalid_copy_with_fn_template_rejection (); goto fail; } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted50.C b/gcc/testsuite/g++.dg/cpp0x/defaulted50.C new file mode 100644 index 00000000000..fea453740e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted50.C @@ -0,0 +1,27 @@ +// PR c++/69005 +// { dg-do compile { target c++11 } } + +template T& declval(); + +template class function; + +template +struct function<_Res(_Arg)> +{ + function() noexcept { } + + function(const function&) { } + + template()(declval<_Arg>()))> + function(_Functor) { } + + _Res operator()(_Arg) const; +}; + +struct Foo { + function Func; +}; + +extern Foo exfoo; +Foo f (exfoo);