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:
parent
684d6ee140
commit
dfc420f8d4
|
@ -549,8 +549,17 @@ expand_intrinsic_vaarg (tree callexp)
|
||||||
{
|
{
|
||||||
parmn = CALL_EXPR_ARG (callexp, 1);
|
parmn = CALL_EXPR_ARG (callexp, 1);
|
||||||
STRIP_NOPS (parmn);
|
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);
|
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
|
/* 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
|
argument, however, is inout and that needs to be fixed to prevent a
|
||||||
warning. Could be casting, so need to check type too? */
|
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. */
|
/* 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);
|
return call_builtin_fn (callexp, BUILT_IN_VA_START, 2, ap, parmn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue