diff mbox series

[committed] d: Fix ICE in expand_intrinsic_vaarg (PR96140)

Message ID 20200730214531.789810-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Fix ICE in expand_intrinsic_vaarg (PR96140) | expand

Commit Message

Iain Buclaw July 30, 2020, 9:45 p.m. UTC
Hi,

This patch fixes an ICE in the D front-end in the va_arg intrinsic
functions.  Both intrinsics did not handler the case where the va_list
object comes from a ref parameter.

Bootstrapped and regression tested on x86_64-linux-gnu, committed to
mainline.

Regards
Iain.

---
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.
---
 gcc/d/intrinsics.cc            | 23 +++++++++++++++++++----
 gcc/testsuite/gdc.dg/pr96140.d | 15 +++++++++++++++
 2 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/pr96140.d
diff mbox series

Patch

diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc
index 28667c63e17..8eec0af60ee 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);
 }
diff --git a/gcc/testsuite/gdc.dg/pr96140.d b/gcc/testsuite/gdc.dg/pr96140.d
new file mode 100644
index 00000000000..d25bb5d3360
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr96140.d
@@ -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);
+}