On Mon, Dec 12, 2016 at 12:03:16PM +0100, Jakub Jelinek wrote:
> On Thu, Dec 08, 2016 at 10:07:59PM +0100, Marek Polacek wrote:
> > 2016-12-08  Marek Polacek  <pola...@redhat.com>
> > 
> >     PR middle-end/78716
> >     * gimplify.c (gimplify_va_arg_expr): Don't require ADDR_EXPR for
> >     Case 1.
> > 
> >     * g++.dg/other/vararg-5.C: New.
> > 
> > diff --git gcc/gimplify.c gcc/gimplify.c
> > index 8611060..08c4faa 100644
> > --- gcc/gimplify.c
> > +++ gcc/gimplify.c
> > @@ -12642,8 +12642,7 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq 
> > *pre_p,
> >    if (have_va_type == error_mark_node)
> >      return GS_ERROR;
> >    have_va_type = targetm.canonical_va_list_type (have_va_type);
> > -  if (have_va_type == NULL_TREE
> > -      && TREE_CODE (valist) == ADDR_EXPR)
> > +  if (have_va_type == NULL_TREE)
> >      /* Handle 'Case 1: Not an array type' from c-common.c/build_va_arg.  */
> >      have_va_type
> >        = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
> 
> This assumes that TREE_TYPE (TREE_TYPE (valist)) is meaningful, which
> isn't always the case.  So, shall it check instead that
> POINTER_TYPE_P (TREE_TYPE (valist))
> instead, or do we have any guarantees valist must be a pointer at this
> point?

Yeah, given
expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (expr)), expr);
in build_va_arg it seems it'll always be a pointer, so the following is
probably safer.

Bootstrap/regtest running on x86_64-linux, ok for trunk if it passes?

2016-12-12  Marek Polacek  <pola...@redhat.com>

        PR middle-end/78716
        * gimplify.c (gimplify_va_arg_expr): Don't require ADDR_EXPR for
        Case 1; check POINTER_TYPE_P instead.

        * g++.dg/other/vararg-5.C: New.

diff --git gcc/gimplify.c gcc/gimplify.c
index 8611060..b738855 100644
--- gcc/gimplify.c
+++ gcc/gimplify.c
@@ -12643,7 +12643,7 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
     return GS_ERROR;
   have_va_type = targetm.canonical_va_list_type (have_va_type);
   if (have_va_type == NULL_TREE
-      && TREE_CODE (valist) == ADDR_EXPR)
+      && POINTER_TYPE_P (TREE_TYPE (valist)))
     /* Handle 'Case 1: Not an array type' from c-common.c/build_va_arg.  */
     have_va_type
       = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
diff --git gcc/testsuite/g++.dg/other/vararg-5.C 
gcc/testsuite/g++.dg/other/vararg-5.C
index e69de29..9327bd6 100644
--- gcc/testsuite/g++.dg/other/vararg-5.C
+++ gcc/testsuite/g++.dg/other/vararg-5.C
@@ -0,0 +1,24 @@
+// PR middle-end/78716
+// { dg-do compile }
+
+template <typename = int, typename = int, typename = int, typename = int,
+                  typename = int>
+                  struct a;
+                  template <typename> struct b;
+                  template <typename = int, typename d = void> class e : 
b<d>::c {
+                    public:
+                        typedef e f;
+                          typedef typename b<d>::c g;
+                            e(__builtin_va_list *s) : g(__builtin_va_arg(*s, 
int)) {}
+                  };
+template <> struct b<void> { typedef e<> c; };
+template <> struct e<> { template <typename h> e(h); };
+template <typename i> class a<i> : public e<i> {};
+template <typename i, typename j, typename k, typename l>
+class a<i, j, k, l> : e<typename a<j>::f> {
+  public:
+      template <typename m, typename n, typename o, typename p>
+         a(a<m, n, o, p>) : a::f(0) {}
+};
+template <typename i, typename j, typename k, typename l> a<> r(i, j, k, l);
+void q() { a<float, float>(r(4, 6, 9, 7)); }

        Marek

Reply via email to