Message ID | af30b5d3-07a7-78e2-d0ea-930cc5e00ae6@acm.org |
---|---|
State | Superseded |
Headers | show |
On 12/16/2016 07:23 AM, Nathan Sidwell wrote: > 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; > } Hmm, we shouldn't get here for an expression we're going to use as an lvalue. Jason
On 01/04/2017 12:40 AM, Jason Merrill wrote: > On 12/16/2016 07:23 AM, Nathan Sidwell wrote: >> 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. */ > Hmm, we shouldn't get here for an expression we're going to use as an > lvalue. I don't think we know we're going to use it as an lvalue early enough. We get here from convert_nontype_argument: else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)) expr = maybe_constant_value (expr); and fail to have 'var' as a constexpr (because it had a bogus initializer, for which we emitted a diagnostic). We then get to: if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)) { tree t = build_integral_nontype_arg_conv (type, expr, complain); and that finds the conversion operator, which needs var as the object expression. I suppose at that point, if expr is not constant we've already lost. Perhaps build_integral_nontype_arg_conv should bail out earlier? Or is the problem in the error recovery of: static constexpr ValueType var = 0; should we unmark the constexprness of var? WDYT? nathan -- Nathan Sidwell
On Wed, Jan 4, 2017 at 9:33 AM, Nathan Sidwell <nathan@acm.org> wrote: > On 01/04/2017 12:40 AM, Jason Merrill wrote: >> On 12/16/2016 07:23 AM, Nathan Sidwell wrote: >>> >>> 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. */ > >> Hmm, we shouldn't get here for an expression we're going to use as an >> lvalue. > > I don't think we know we're going to use it as an lvalue early enough. We > get here from convert_nontype_argument: > else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)) > expr = maybe_constant_value (expr); OK, that looks like the problem; we shouldn't be calling maybe_constant_value before we perform the conversion. Jason
2016-12-15 Nathan Sidwell <nathan@acm.org> 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;