diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2020-07-16 18:34:18 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2020-07-30 23:44:31 +0200 |
commit | dfc420f8d4492dbf5f45df4fecf93cb9645c0d7b (patch) | |
tree | 66848001f1fae4622a5aabd3813239d8cb05a08d /gcc/d | |
parent | 684d6ee140af6585c18c8790f8f5bddfcc6bd153 (diff) | |
download | gcc-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.cc | 23 |
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); } |