d: Fix ICE in expand_intrinsic_vaarg

Both intrinsics did not handle the case where the va_list object comes
from a ref parameter.

gcc/d/ChangeLog:

	PR d/96140
	* intrinsics.cc (expand_intrinsic_vaarg): Handle ref parameters as
	arguments to va_arg().
	(expand_intrinsic_vastart): Handle ref parameters as arguments to
	va_start().

gcc/testsuite/ChangeLog:

	PR d/96140
	* gdc.dg/pr96140.d: New test.
This commit is contained in:
Iain Buclaw 2020-07-16 18:34:18 +02:00
parent 684d6ee140
commit dfc420f8d4
2 changed files with 34 additions and 4 deletions

View File

@ -549,8 +549,17 @@ expand_intrinsic_vaarg (tree callexp)
{
parmn = CALL_EXPR_ARG (callexp, 1);
STRIP_NOPS (parmn);
gcc_assert (TREE_CODE (parmn) == ADDR_EXPR);
parmn = TREE_OPERAND (parmn, 0);
/* The `ref' argument to va_arg is either an address or reference,
get the value of it. */
if (TREE_CODE (parmn) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (parmn)))
parmn = build_deref (parmn);
else
{
gcc_assert (TREE_CODE (parmn) == ADDR_EXPR);
parmn = TREE_OPERAND (parmn, 0);
}
type = TREE_TYPE (parmn);
}
@ -584,10 +593,16 @@ expand_intrinsic_vastart (tree callexp)
/* The va_list argument should already have its address taken. The second
argument, however, is inout and that needs to be fixed to prevent a
warning. Could be casting, so need to check type too? */
gcc_assert (TREE_CODE (ap) == ADDR_EXPR && TREE_CODE (parmn) == ADDR_EXPR);
gcc_assert (TREE_CODE (ap) == ADDR_EXPR
|| (TREE_CODE (ap) == PARM_DECL
&& POINTER_TYPE_P (TREE_TYPE (ap))));
/* Assuming nobody tries to change the return type. */
parmn = TREE_OPERAND (parmn, 0);
if (TREE_CODE (parmn) != PARM_DECL)
{
gcc_assert (TREE_CODE (parmn) == ADDR_EXPR);
parmn = TREE_OPERAND (parmn, 0);
}
return call_builtin_fn (callexp, BUILT_IN_VA_START, 2, ap, parmn);
}

View File

@ -0,0 +1,15 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96140
// { dg-do compile }
module pr94140;
import core.stdc.stdarg;
void test_va_arg(ref int a, ...)
{
return va_arg!int(_argptr, a);
}
void test_va_start(ref va_list a, ...)
{
return va_start(a, a);
}