Jason,
this patch fixes an ICE that happens after error recovery of a constexpr
object that has a bad initializer.
your patch introduced this regression:
* tree.c (obvalue_p): Rename from lvalue_p.
(lvalue_p): Define for c-common.
* call.c, cp-tree.h, cvt.c, init.c: Adjust.
* typeck.c: Adjust.
(cp_build_addr_expr_1): Remove obsolete code.
that cp_build_addr_expr_1 change turns out not quite obsolete.
when cxx_eval_constant_expression finds a nonconstant expression it
returns a TREE without TREE_CONSTANT set.
else if (non_constant_p && TREE_CONSTANT (r))
{
/* This isn't actually constant, so unset TREE_CONSTANT. */
...
else // THIS CASE HAPPENS
r = build_nop (TREE_TYPE (r), r);
TREE_CONSTANT (r) = false;
}
In this case r is the VAR_DECL for 'var'. And cp_build_addr_expr_1 is
called to build the object expression to apply ValueType::operator int ().
This patch simply strips the NOP expr. I placed that code in the
lvalue_kind checking block, because of the comment in the switch statement:
CASE_CONVERT:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
/* We should have handled this above in the lvalue_kind check. */
gcc_unreachable ();
Alternatively we could check if we've met this case just there. (which
was the original location of the obsolete code)
ok?
nathan
--
Nathan Sidwell
2016-12-15 Nathan Sidwell <[email protected]>
PR c++/78765
* typeck.c (cp_build_addr_expr_1): Cope with failed constexpr eval
of incoming arg.
PR c++/78765
* g++.dg/cpp0x/pr78765.C: New.
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 243692)
+++ cp/typeck.c (working copy)
@@ -5645,9 +5645,24 @@ cp_build_addr_expr_1 (tree arg, bool str
else
error ("taking address of xvalue (rvalue reference)");
}
+
+ /* If ARG comes from a failed constexpr evaluation, it might be
+ wrapped in a NOP_EXPR to remove TREE_CONSTANT. */
+ if (kind == clk_class && TREE_CODE (arg) == NOP_EXPR)
+ {
+ gcc_assert (!TREE_CONSTANT (arg)
+ && TREE_CONSTANT (TREE_OPERAND (arg, 0))
+ && same_type_p (argtype,
+ TREE_TYPE (TREE_OPERAND (arg, 0))));
+ arg = TREE_OPERAND (arg, 0);
+ }
}
if (TREE_CODE (argtype) == REFERENCE_TYPE)
Index: testsuite/g++.dg/cpp0x/pr78765.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr78765.C (revision 0)
+++ testsuite/g++.dg/cpp0x/pr78765.C (working copy)
@@ -0,0 +1,15 @@
+// PR c++/78765
+// { dg-do compile { target c++11 } }
+
+// ICE with failed constexpr object and member fn call
+
+struct ValueType {
+ constexpr operator int() const {return field;}
+ int field;
+};
+
+static constexpr ValueType var = 0; // { dg-error "conversion" }
+
+template <int> class ValueTypeInfo;
+
+ValueTypeInfo<var> x;