This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] [PR c++/85437] accept static_casted ptrmem in constexpr
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: Alexandre Oliva <aoliva at redhat dot com>, gcc-patches List <gcc-patches at gcc dot gnu dot org>, Nathan Sidwell <nathan at acm dot org>
- Date: Thu, 19 Apr 2018 17:58:42 +0200
- Subject: Re: [PATCH] [PR c++/85437] accept static_casted ptrmem in constexpr
- References: <or604puqhd.fsf@lxoliva.fsfla.org> <CADzB+2mcor+rs3WgC-tdbcy+9mao+ugK-DTgbDfZT3sjvs-eqw@mail.gmail.com> <20180418125934.GS8577@tucnak> <20180418131419.GR5866@tucnak> <20180418193253.GS5866@tucnak>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Wed, Apr 18, 2018 at 09:32:53PM +0200, Jakub Jelinek wrote:
> In any case, this reinterpret_cast constexpr pedantic stuff looks too
> large/risky at this point to me, I wonder if we accept-invalid even the
> simple constexpr int a = reinterpret_cast<int> (1); whether it is not ok for
> GCC8 to not error out on reinterpret_cast from PTRMEM_CSTs too, essentially
> just use Alex's patch for expr.c and the first hunk from this patch from
> constexpr.c, plus the new testcases and deal with the rest for stage1.
> Thoughts on this?
I've tried following patch, but it regresses
+FAIL: g++.dg/conversion/ptrmem5.C -std=c++11 (test for excess errors)
+FAIL: g++.dg/conversion/ptrmem5.C -std=c++14 (test for excess errors)
+FAIL: g++.dg/conversion/ptrmem5.C -std=c++98 (test for excess errors)
+FAIL: g++.dg/init/static2.C -std=c++11 (test for excess errors)
+UNRESOLVED: g++.dg/init/static2.C -std=c++11 compilation failed to produce executable
+FAIL: g++.dg/init/static2.C -std=c++14 (test for excess errors)
+UNRESOLVED: g++.dg/init/static2.C -std=c++14 compilation failed to produce executable
+FAIL: g++.dg/init/static2.C -std=c++98 (test for excess errors)
+UNRESOLVED: g++.dg/init/static2.C -std=c++98 compilation failed to produce executable
apparently a reinterpret_cast in that case is something that shouldn't be
handled by cxx_eval_constant_expression, or we ICE. And if instead of the
constexpr.c hunk I try to add || can_convert (type, TREE_TYPE (op), tf_none)
then the testcases from the PR don't work anymore.
So I'm afraid I need to give up on this, Alex, if you have ideas what to do,
I'd appreciate if you could look at this, otherwise we'll need to defer this
P1 for next week.
--- gcc/cp/constexpr.c.jj 2018-04-13 10:33:03.078658240 +0200
+++ gcc/cp/constexpr.c 2018-04-18 15:53:07.936504106 +0200
@@ -4596,20 +4596,7 @@ cxx_eval_constant_expression (const cons
&& !TYPE_PTRMEM_P (type))
op = cplus_expand_constant (op);
if (TREE_CODE (op) == PTRMEM_CST && tcode == NOP_EXPR)
- {
- if (same_type_ignoring_top_level_qualifiers_p (type,
- TREE_TYPE (op))
- || can_convert_qual (type, op))
- return cp_fold_convert (type, op);
- else
- {
- if (!ctx->quiet)
- error_at (EXPR_LOC_OR_LOC (t, input_location),
- "a reinterpret_cast is not a constant expression");
- *non_constant_p = true;
- return t;
- }
- }
+ return cp_fold_convert (type, op);
if (POINTER_TYPE_P (type) && TREE_CODE (op) == INTEGER_CST)
{
--- gcc/cp/expr.c.jj 2018-03-09 23:22:23.682236182 +0100
+++ gcc/cp/expr.c 2018-04-18 14:24:52.692310448 +0200
@@ -50,11 +50,36 @@ cplus_expand_constant (tree cst)
while (!same_type_p (DECL_CONTEXT (member),
TYPE_PTRMEM_CLASS_TYPE (type)))
{
+ tree t1 = TYPE_MAIN_VARIANT (DECL_CONTEXT (member));
+ tree t2 = TYPE_MAIN_VARIANT (TYPE_PTRMEM_CLASS_TYPE (type));
+
+ if (can_convert (t2, t1, 0))
+ {
+ base_kind kind;
+ tree binfo = lookup_base (t1, t2, ba_unique, &kind, 0);
+ if (binfo != error_mark_node
+ && kind != bk_via_virtual)
+ cst = size_binop (MINUS_EXPR, cst, BINFO_OFFSET (binfo));
+ break;
+ }
+
+ if (can_convert (t1, t2, 0))
+ {
+ base_kind kind;
+ tree binfo = lookup_base (t2, t1, ba_unique, &kind, 0);
+ if (binfo != error_mark_node
+ && kind != bk_via_virtual)
+ cst = size_binop (PLUS_EXPR, cst, BINFO_OFFSET (binfo));
+ break;
+ }
+
/* The MEMBER must have been nestled within an
anonymous aggregate contained in TYPE. Find the
anonymous aggregate. */
member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
DECL_CONTEXT (member));
+ if (!member)
+ break;
cst = size_binop (PLUS_EXPR, cst, byte_position (member));
}
cst = fold (build_nop (type, cst));
--- gcc/testsuite/g++.dg/cpp0x/pr85437.C.jj 2018-04-18 14:25:50.655332890 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437.C 2018-04-18 14:28:34.234396893 +0200
@@ -0,0 +1,17 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { int a; constexpr A() : a(0) {} };
+struct B : A { int x; constexpr B() : x(0) {} };
+struct X { int z; constexpr X() : z(0) {} };
+struct C : X, B {};
+constexpr int C::*cbx = &B::x;
+constexpr int B::*bx = &B::x;
+constexpr int A::*abx = static_cast<int(A::*)>(&B::x); // { dg-bogus "not a constant expression" }
+
+constexpr const C y;
+constexpr const B& yb = y;
+constexpr const A& ya = y;
+constexpr int const *pcbx = &(y.*cbx);
+constexpr int const *pbx = &(y.*bx);
+constexpr int const *pabx = &(ya.*abx);
--- gcc/testsuite/g++.dg/cpp0x/pr85437-2.C.jj 2018-04-18 14:25:50.654332889 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437-2.C 2018-04-18 14:28:45.613401350 +0200
@@ -0,0 +1,8 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B : A { int x; };
+
+constexpr int A::*abx
+= reinterpret_cast<int(A::*)>(&B::x); // { dg-error "reinterpret.*constant" "" { xfail *-*-* } }
--- gcc/testsuite/g++.dg/cpp0x/pr85437-3.C.jj 2018-04-18 14:25:50.655332890 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437-3.C 2018-04-18 14:29:57.691429562 +0200
@@ -0,0 +1,8 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { int y; };
+struct B { int x; };
+struct C : A, B {};
+constexpr int C::*pci = &B::x;
+constexpr int A::*pai = static_cast<int A::*>(static_cast<int C::*>(&B::x)); // { dg-bogus "not a constant expression" }
--- gcc/testsuite/g++.dg/cpp0x/pr85437-4.C.jj 2018-04-18 14:29:29.028418341 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437-4.C 2018-04-18 14:29:39.829422569 +0200
@@ -0,0 +1,8 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B { int x; };
+struct C : A, B {};
+constexpr int C::*pci = &B::x;
+constexpr int A::*pai = static_cast<int A::*>(pci); // { dg-bogus "not a constant expression" }
Jakub