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 <[email protected]>
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