Hi!

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.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?  Alternatively it could if (TREE_TYPE (t) && ...

On a related note, I wonder if the
        return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
a few lines below is correct, VCE isn't always an lvalue, only if it is used
in non-rvalue contexts.  So, shouldn't it be instead:
        return (RECUR (from, (TREE_CODE (t) == VIEW_CONVERT_EXPR
                              ? want_rval : rval)));
Don't have a testcase where it would matter though.

2018-01-18  Jakub Jelinek  <ja...@redhat.com>

        PR c++/83918
        * constexpr.c (potential_constant_expression_1)
        <case VIEW_CONVERT_EXPR>: Don't check for INTEGER_CST to pointer
        type conversion for location wrappers.

        * g++.dg/cpp1z/pr83918.C: New test.

--- gcc/cp/constexpr.c.jj       2018-01-17 22:00:13.624228171 +0100
+++ gcc/cp/constexpr.c  2018-01-18 10:38:07.357469094 +0100
@@ -5385,7 +5385,8 @@ potential_constant_expression_1 (tree t,
         may change to something more specific to type-punning (DR 1312).  */
       {
         tree from = TREE_OPERAND (t, 0);
-       if (POINTER_TYPE_P (TREE_TYPE (t))
+       if (!location_wrapper_p (t)
+           && POINTER_TYPE_P (TREE_TYPE (t))
            && TREE_CODE (from) == INTEGER_CST
            && !integer_zerop (from))
          {
--- gcc/testsuite/g++.dg/cpp1z/pr83918.C.jj     2018-01-18 10:46:04.405439296 
+0100
+++ gcc/testsuite/g++.dg/cpp1z/pr83918.C        2018-01-18 10:45:42.934442290 
+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