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

Reply via email to