aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2020-07-16 18:34:18 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2020-07-30 23:44:31 +0200
commitdfc420f8d4492dbf5f45df4fecf93cb9645c0d7b (patch)
tree66848001f1fae4622a5aabd3813239d8cb05a08d /gcc/d
parent684d6ee140af6585c18c8790f8f5bddfcc6bd153 (diff)
downloadgcc-dfc420f8d4492dbf5f45df4fecf93cb9645c0d7b.zip
gcc-dfc420f8d4492dbf5f45df4fecf93cb9645c0d7b.tar.gz
gcc-dfc420f8d4492dbf5f45df4fecf93cb9645c0d7b.tar.bz2
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.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/intrinsics.cc23
1 files changed, 19 insertions, 4 deletions
diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc
index 28667c6..8eec0af 100644
--- a/gcc/d/intrinsics.cc
+++ b/gcc/d/intrinsics.cc
@@ -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);
}