On Mon, Jan 22, 2018 at 04:49:34PM -0500, Jason Merrill wrote: > On Thu, Jan 18, 2018 at 6:13 PM, Jakub Jelinek <ja...@redhat.com> wrote: > > Before location wrappers were introduced, the > > potential_constant_expression_1 > > assumption that a VIEW_CONVERT_EXPR must have non-NULL type was right, > > if it is a type dependent reinterpret cast, it would be > > REINTERPRET_CAST_EXPR instead. > > > > Location wrappers around decls can have NULL type, if the decl they wrap > > also has NULL type. > > Hmm, why would a decl have NULL type? Are we wrapping a CONST_DECL in > VIEW_CONVERT_EXPR? They should get NON_LVALUE_EXPR, since they aren't > lvalues (except the objc++ ones that have TREE_STATIC set).
So, do you want following instead, if it passes bootstrap/regtest? 2018-01-22 Jakub Jelinek <ja...@redhat.com> PR c++/83918 * tree.c (maybe_wrap_with_location): Use NON_LVALUE_EXPR rather than VIEW_CONVERT_EXPR to wrap CONST_DECLs. * g++.dg/cpp1z/pr83918.C: New test. --- gcc/tree.c.jj 2018-01-16 16:16:37.124694238 +0100 +++ gcc/tree.c 2018-01-22 23:53:58.171837029 +0100 @@ -14085,8 +14085,10 @@ maybe_wrap_with_location (tree expr, loc if (EXCEPTIONAL_CLASS_P (expr)) return expr; - tree_code code = (CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST - ? NON_LVALUE_EXPR : VIEW_CONVERT_EXPR); + tree_code code + = (((CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST) + || (TREE_CODE (expr) == CONST_DECL && !TREE_STATIC (expr))) + ? NON_LVALUE_EXPR : VIEW_CONVERT_EXPR); tree wrapper = build1_loc (loc, code, TREE_TYPE (expr), expr); /* Mark this node as being a wrapper. */ EXPR_LOCATION_WRAPPER_P (wrapper) = 1; --- gcc/testsuite/g++.dg/cpp1z/pr83918.C.jj 2018-01-22 23:54:40.824824960 +0100 +++ gcc/testsuite/g++.dg/cpp1z/pr83918.C 2018-01-22 23:54:40.824824960 +0100 @@ -0,0 +1,32 @@ +// PR c++/83918 +// { dg-do compile } +// { dg-options "-std=c++17" } + +constexpr unsigned +foo (unsigned x, unsigned y) +{ + return x > y ? x : y; +} + +template <typename, typename> struct A; +template <auto ...> struct B; +template <auto S, auto ... T, auto U, auto ... V> +struct A <B <S, T...>, B <U, V...>> +{ + enum : unsigned + { + u = foo (sizeof (S), sizeof (U)), + v = A <B <T...>, B <V...>>::w, + w = foo (u, v) + }; +}; + +template <> +struct A <B <>, B <>> +{ + enum : unsigned { w = 0 }; +}; + +constexpr static const auto v { A <B <1,2,3,4,5,6,7,8,9>, + B <9,8,7,6,5,4,3,2,1>>::w }; +static_assert (v == sizeof (int)); Jakub