commit 44cdacef5b56c91e2787f737f0ea90aa66790436
Author: Jason Merrill <jason@redhat.com>
Date: Wed Mar 27 14:16:14 2013 -0400
PR c++/56728
* semantics.c (potential_constant_expression_1) [NOP_EXPR]: Reject
conversion from integer to pointer.
(cxx_eval_constant_expression): Likewise.
(cxx_eval_indirect_ref): Use the folded operand if we still think
this might be constant.
@@ -7661,6 +7661,8 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t,
if (r == NULL_TREE)
{
+ if (addr && op0 != orig_op0)
+ return build1 (INDIRECT_REF, TREE_TYPE (t), op0);
if (!addr)
VERIFY_CONSTANT (t);
return t;
@@ -8056,6 +8058,16 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
non_constant_p, overflow_p);
if (*non_constant_p)
return t;
+ if (POINTER_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (op) == INTEGER_CST
+ && !integer_zerop (op))
+ {
+ if (!allow_non_constant)
+ error_at (EXPR_LOC_OR_HERE (t),
+ "reinterpret_cast from integer to pointer");
+ *non_constant_p = true;
+ return t;
+ }
if (op == oldop)
/* We didn't fold at the top so we could check for ptr-int
conversion. */
@@ -8452,6 +8464,15 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
may change to something more specific to type-punning (DR 1312). */
{
tree from = TREE_OPERAND (t, 0);
+ if (POINTER_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (from) == INTEGER_CST
+ && !integer_zerop (from))
+ {
+ if (flags & tf_error)
+ error_at (EXPR_LOC_OR_HERE (t),
+ "reinterpret_cast from integer to pointer");
+ return false;
+ }
return (potential_constant_expression_1
(from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags));
}
new file mode 100644
@@ -0,0 +1,37 @@
+// PR c++/56728
+// { dg-require-effective-target c++11 }
+
+class B {
+public:
+ static B instance;
+ class Inner
+ {
+ public:
+ class Wuzi
+ {
+ unsigned int m;
+ } m_Class[3];
+ unsigned m_Int[4];
+ };
+
+ constexpr static Inner & getInner()
+ {
+ /* I am surprised this is considered a constexpr */
+ return *((Inner *)4);
+ } // { dg-error "reinterpret_cast" }
+};
+
+B B::instance;
+
+class A
+{
+public:
+ constexpr A(B &bridge, B::Inner &bridge2, unsigned char index)
+ : m_Bridge(bridge), m_Wuz(bridge2.m_Class[index])
+ {}
+
+ B &m_Bridge;
+ B::Inner::Wuzi &m_Wuz;
+};
+A works{B::instance, B::getInner(), 3};
+A crashnkill[1]{{B::instance, B::getInner(), 3}};