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