c++: Fix ICE on valid involving variadic constructor [PR111592]

Message ID 01020190984579a0-d9edaf97-be78-416c-aa9b-203556ebadb9-000000@eu-west-1.amazonses.com
State New
Headers
Series c++: Fix ICE on valid involving variadic constructor [PR111592] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Simon Martin July 9, 2024, 4:13 p.m. UTC
  We currently ICE upon the following valid code, due to the fix made through
commit 9efe5fbde1e8

=== cut here ===
struct ignore { ignore(...) {} };
template<class... Args>
void InternalCompilerError(Args... args)
{ ignore{ ignore(args) ... }; }
int main() { InternalCompilerError(0, 0); }
=== cut here ===

Change 9efe5fbde1e8 avoids infinite recursion in build_over_call by returning
error_mark_node if one invokes ignore::ignore(...) with an argument of type
ignore, because otherwise we end up calling convert_arg_to_ellipsis for that
argument, and recurse into build_over_call with the exact same parameters.

This patch tightens the condition to only return error_mark_node if there's one
and only one parameter to the call being processed - otherwise we won't
infinitely recurse.

Successfully tested on x86_64-pc-linux-gnu.

	PR c++/111592

gcc/cp/ChangeLog:

	* call.cc (build_over_call): Only error out if there's a single
	parameter of type A in a call to A::A(...).

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/variadic186.C: New test.

---
 gcc/cp/call.cc                           |  1 +
 gcc/testsuite/g++.dg/cpp0x/variadic186.C | 11 +++++++++++
 2 files changed, 12 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic186.C

-- 
2.44.0
  

Comments

Jason Merrill July 17, 2024, 7:21 p.m. UTC | #1
On 7/9/24 12:13 PM, Simon Martin wrote:
> We currently ICE upon the following valid code, due to the fix made through
> commit 9efe5fbde1e8

OK.

> === cut here ===
> struct ignore { ignore(...) {} };
> template<class... Args>
> void InternalCompilerError(Args... args)
> { ignore{ ignore(args) ... }; }
> int main() { InternalCompilerError(0, 0); }
> === cut here ===
> 
> Change 9efe5fbde1e8 avoids infinite recursion in build_over_call by returning
> error_mark_node if one invokes ignore::ignore(...) with an argument of type
> ignore, because otherwise we end up calling convert_arg_to_ellipsis for that
> argument, and recurse into build_over_call with the exact same parameters.
> 
> This patch tightens the condition to only return error_mark_node if there's one
> and only one parameter to the call being processed - otherwise we won't
> infinitely recurse.
> 
> Successfully tested on x86_64-pc-linux-gnu.
> 
> 	PR c++/111592
> 
> gcc/cp/ChangeLog:
> 
> 	* call.cc (build_over_call): Only error out if there's a single
> 	parameter of type A in a call to A::A(...).
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/variadic186.C: New test.
> 
> ---
>   gcc/cp/call.cc                           |  1 +
>   gcc/testsuite/g++.dg/cpp0x/variadic186.C | 11 +++++++++++
>   2 files changed, 12 insertions(+)
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic186.C
> 
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 83070b2f633..0e4e9a80408 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -10335,6 +10335,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
>   	  a = decay_conversion (a, complain);
>   	}
>         else if (DECL_CONSTRUCTOR_P (fn)
> +	       && vec_safe_length (args) == 1
>   	       && same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (fn),
>   							     TREE_TYPE (a)))
>   	{
> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic186.C b/gcc/testsuite/g++.dg/cpp0x/variadic186.C
> new file mode 100644
> index 00000000000..4a25a1a96bf
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/variadic186.C
> @@ -0,0 +1,11 @@
> +// PR c++/111592
> +// { dg-do compile { target c++11 } }
> +
> +struct ignore { ignore(...) {} };
> +
> +template<class... Args>
> +void InternalCompilerError(Args... args)
> +{ ignore{ ignore(args) ... }; }
> +
> +int main()
> +{ InternalCompilerError(0, 0); }
  

Patch

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 83070b2f633..0e4e9a80408 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10335,6 +10335,7 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	  a = decay_conversion (a, complain);
 	}
       else if (DECL_CONSTRUCTOR_P (fn)
+	       && vec_safe_length (args) == 1
 	       && same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (fn),
 							     TREE_TYPE (a)))
 	{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic186.C b/gcc/testsuite/g++.dg/cpp0x/variadic186.C
new file mode 100644
index 00000000000..4a25a1a96bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic186.C
@@ -0,0 +1,11 @@ 
+// PR c++/111592
+// { dg-do compile { target c++11 } }
+
+struct ignore { ignore(...) {} };
+
+template<class... Args>
+void InternalCompilerError(Args... args)
+{ ignore{ ignore(args) ... }; }
+
+int main()
+{ InternalCompilerError(0, 0); }