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  <nat...@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;

Reply via email to