The problem in this testcase was that the initializer looked constant
to is_nondependent_constant_expression, but instantiating it found the
conversion error, but because fold_non_dependent_expr passed tf_none
to the instantiation, we didn't give an error.  store_init_value then
happily stuck the error_mark_node in DECL_INITIAL, leading to an abort
later on when we find it without seen_error().

Basically, if we're going to keep around the result of the
instantiation, we need to pass in the appropriate complain argument.
So this patch adds a complain parameter to fold_non_dependent_expr.
It also changes the default to tf_warning_or_error, like it was in
older releases.

This change meant that the use in build_cxx_call would start to
diagnose conversion problems without the relevant information about
which parameter the conversion was for, so I've disabled that folding
when we're in a template.

In store_init_value, I also think we want to go back to the original
uninstantiated initializer if folding doesn't actually produce a
constant value: we want something that's OK to re-tsubst later.

I considered switching store_init_value back to using
instantiate_non_dependent_expr; the switch to fold_non_dependent_expr
was motivated by a problem with force_paren_expr making an expression
dependent that wasn't previously.  To address that, since we're using
VIEW_CONVERT_EXPR for location wrappers now, let's try using it here
as well.  But I ended up staying with fold_non_dependent_expr anyway.

Tested x86_64-pc-linux-gnu, applying to trunk.  For GCC 8 I'm applying
a much more localized patch, that just switches to tf_warning_or_error
for store_init_value.
commit d78857c84e5daf8b8f4cfa9db0833748e23f76b1
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Jun 21 14:54:59 2018 -0400

            PR c++/86219 - ICE with erroneous initializer in template.
    
            * constexpr.c (fold_non_dependent_expr): Add complain parm.
            * call.c, expr.c, init.c, pt.c, semantics.c, typeck.c, typeck2.c:
            Pass it.
            * call.c (build_cxx_call): Don't mess with builtins in a template.
            * typeck2.c (store_init_value): If fold_non_dependent_expr didn't
            produce a constant value, go back to the uninstantiated form.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e417590e97d..aa0e696972a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -544,7 +544,7 @@ null_ptr_cst_p (tree t)
     }
   else if (CP_INTEGRAL_TYPE_P (type))
     {
-      t = fold_non_dependent_expr (t);
+      t = fold_non_dependent_expr (t, tf_none);
       STRIP_NOPS (t);
       if (integer_zerop (t) && !TREE_OVERFLOW (t))
 	return true;
@@ -8796,6 +8796,7 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
 
   /* Check that arguments to builtin functions match the expectations.  */
   if (fndecl
+      && !processing_template_decl
       && DECL_BUILT_IN (fndecl)
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
     {
@@ -8804,7 +8805,7 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
       /* We need to take care that values to BUILT_IN_NORMAL
          are reduced.  */
       for (i = 0; i < nargs; i++)
-	argarray[i] = fold_non_dependent_expr (argarray[i]);
+	argarray[i] = maybe_constant_value (argarray[i]);
 
       if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl,
 					     nargs, argarray))
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index dea2a4e57b3..365296d6e3b 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -5179,12 +5179,20 @@ clear_cv_and_fold_caches (void)
 /* Like maybe_constant_value but first fully instantiate the argument.
 
    Note: this is equivalent to instantiate_non_dependent_expr_sfinae
-   (t, tf_none) followed by maybe_constant_value but is more efficient,
-   because calls instantiation_dependent_expression_p and
-   potential_constant_expression at most once.  */
+   (t, complain) followed by maybe_constant_value but is more efficient,
+   because it calls instantiation_dependent_expression_p and
+   potential_constant_expression at most once.
+
+   Callers should generally pass their active complain, or if they are in a
+   non-template, diagnosing context, they can use the default of
+   tf_warning_or_error.  Callers that might be within a template context, don't
+   have a complain parameter, and aren't going to remember the result for long
+   (e.g. null_ptr_cst_p), can pass tf_none and deal with error_mark_node
+   appropriately.  */
 
 tree
-fold_non_dependent_expr (tree t)
+fold_non_dependent_expr (tree t,
+			 tsubst_flags_t complain /* = tf_warning_or_error */)
 {
   if (t == NULL_TREE)
     return NULL_TREE;
@@ -5201,7 +5209,7 @@ fold_non_dependent_expr (tree t)
       if (is_nondependent_constant_expression (t))
 	{
 	  processing_template_decl_sentinel s;
-	  t = instantiate_non_dependent_expr_internal (t, tf_none);
+	  t = instantiate_non_dependent_expr_internal (t, complain);
 
 	  if (type_unknown_p (t)
 	      || BRACE_ENCLOSED_INITIALIZER_P (t))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 264bba53f0d..89b6555c09f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7536,7 +7536,7 @@ extern tree cxx_constant_value			(tree, tree = NULL_TREE);
 extern tree cxx_constant_init			(tree, tree = NULL_TREE);
 extern tree maybe_constant_value		(tree, tree = NULL_TREE);
 extern tree maybe_constant_init			(tree, tree = NULL_TREE);
-extern tree fold_non_dependent_expr		(tree);
+extern tree fold_non_dependent_expr		(tree, tsubst_flags_t = tf_warning_or_error);
 extern tree fold_simple				(tree);
 extern bool is_sub_constant_expr                (tree);
 extern bool reduced_constant_expression_p       (tree);
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 133a01b8a51..93477bcd12f 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -353,7 +353,13 @@ fold_for_warn (tree x)
   /* It's not generally safe to fully fold inside of a template, so
      call fold_non_dependent_expr instead.  */
   if (processing_template_decl)
-    return fold_non_dependent_expr (x);
+    {
+      tree f = fold_non_dependent_expr (x, tf_none);
+      if (f == error_mark_node)
+	return x;
+      else
+	return f;
+    }
 
   return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
 }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 810a776a3c8..76ce0b829dd 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2931,7 +2931,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 
   /* Lots of logic below depends on whether we have a constant number of
      elements, so go ahead and fold it now.  */
-  const_tree cst_outer_nelts = fold_non_dependent_expr (outer_nelts);
+  const_tree cst_outer_nelts = fold_non_dependent_expr (outer_nelts, complain);
 
   /* If our base type is an array, then make sure we know how many elements
      it has.  */
@@ -3731,7 +3731,7 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
       /* Try to determine the constant value only for the purposes
 	 of the diagnostic below but continue to use the original
 	 value and handle const folding later.  */
-      const_tree cst_nelts = fold_non_dependent_expr (nelts);
+      const_tree cst_nelts = fold_non_dependent_expr (nelts, complain);
 
       /* The expression in a noptr-new-declarator is erroneous if it's of
 	 non-class type and its value before converting to std::size_t is
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d6410d71555..ed74c27c230 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16881,7 +16881,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	/* Don't instantiate the THEN_CLAUSE. */;
       else
 	{
-	  bool inhibit = integer_zerop (fold_non_dependent_expr (tmp));
+	  tree folded = fold_non_dependent_expr (tmp, complain);
+	  bool inhibit = integer_zerop (folded);
 	  if (inhibit)
 	    ++c_inhibit_evaluation_warnings;
 	  RECUR (THEN_CLAUSE (t));
@@ -16894,7 +16895,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	/* Don't instantiate the ELSE_CLAUSE. */;
       else if (ELSE_CLAUSE (t))
 	{
-	  bool inhibit = integer_nonzerop (fold_non_dependent_expr (tmp));
+	  tree folded = fold_non_dependent_expr (tmp, complain);
+	  bool inhibit = integer_nonzerop (folded);
 	  begin_else_clause (stmt);
 	  if (inhibit)
 	    ++c_inhibit_evaluation_warnings;
@@ -18535,7 +18537,7 @@ tsubst_copy_and_build (tree t,
       {
 	tree cond = RECUR (TREE_OPERAND (t, 0));
 	cond = mark_rvalue_use (cond);
-	tree folded_cond = fold_non_dependent_expr (cond);
+	tree folded_cond = fold_non_dependent_expr (cond, complain);
 	tree exp1, exp2;
 
 	if (TREE_CODE (folded_cond) == INTEGER_CST)
@@ -22100,7 +22102,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	 corresponding parameter is type-dependent.  Make any necessary
 	 adjustments based on whether arg is a reference.  */
       if (CONSTANT_CLASS_P (arg))
-	parm = fold_non_dependent_expr (parm);
+	parm = fold_non_dependent_expr (parm, complain);
       else if (REFERENCE_REF_P (arg))
 	{
 	  tree sub = TREE_OPERAND (arg, 0);
@@ -25873,7 +25875,7 @@ build_non_dependent_expr (tree expr)
       /* Don't do this during concept expansion either and for
          the same reason.  */
       && !expanding_concept ())
-    fold_non_dependent_expr (expr);
+    fold_non_dependent_expr (expr, tf_none);
 
   STRIP_ANY_LOCATION_WRAPPER (expr);
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index da75f30885f..c779137da45 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8676,7 +8676,7 @@ finish_static_assert (tree condition, tree message, location_t location,
   /* Fold the expression and convert it to a boolean value. */
   condition = perform_implicit_conversion_flags (boolean_type_node, condition,
 						 complain, LOOKUP_NORMAL);
-  condition = fold_non_dependent_expr (condition);
+  condition = fold_non_dependent_expr (condition, complain);
 
   if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
     /* Do nothing; the condition is satisfied. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 936de9fe5c6..3a4f1cdf479 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4163,7 +4163,7 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
       || TREE_NO_WARNING (op))
     return;
 
-  tree cop = fold_non_dependent_expr (op);
+  tree cop = fold_non_dependent_expr (op, complain);
 
   if (TREE_CODE (cop) == ADDR_EXPR
       && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0))
@@ -4480,7 +4480,7 @@ cp_build_binary_op (location_t location,
 	      || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
 	{
 	  enum tree_code tcode0 = code0, tcode1 = code1;
-	  tree cop1 = fold_non_dependent_expr (op1);
+	  tree cop1 = fold_non_dependent_expr (op1, complain);
 	  doing_div_or_mod = true;
 	  warn_for_div_by_zero (location, cop1);
 
@@ -4519,7 +4519,7 @@ cp_build_binary_op (location_t location,
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
       {
-	tree cop1 = fold_non_dependent_expr (op1);
+	tree cop1 = fold_non_dependent_expr (op1, complain);
 	doing_div_or_mod = true;
 	warn_for_div_by_zero (location, cop1);
       }
@@ -4614,7 +4614,7 @@ cp_build_binary_op (location_t location,
 	}
       else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
 	{
-	  tree const_op1 = fold_non_dependent_expr (op1);
+	  tree const_op1 = fold_non_dependent_expr (op1, complain);
 	  if (TREE_CODE (const_op1) != INTEGER_CST)
 	    const_op1 = op1;
 	  result_type = type0;
@@ -4660,10 +4660,10 @@ cp_build_binary_op (location_t location,
 	}
       else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
 	{
-	  tree const_op0 = fold_non_dependent_expr (op0);
+	  tree const_op0 = fold_non_dependent_expr (op0, complain);
 	  if (TREE_CODE (const_op0) != INTEGER_CST)
 	    const_op0 = op0;
-	  tree const_op1 = fold_non_dependent_expr (op1);
+	  tree const_op1 = fold_non_dependent_expr (op1, complain);
 	  if (TREE_CODE (const_op1) != INTEGER_CST)
 	    const_op1 = op1;
 	  result_type = type0;
@@ -5370,8 +5370,8 @@ cp_build_binary_op (location_t location,
       /* OP0 and/or OP1 might have side-effects.  */
       op0 = cp_save_expr (op0);
       op1 = cp_save_expr (op1);
-      op0 = fold_non_dependent_expr (op0);
-      op1 = fold_non_dependent_expr (op1);
+      op0 = fold_non_dependent_expr (op0, complain);
+      op1 = fold_non_dependent_expr (op1, complain);
       if (doing_div_or_mod
 	  && sanitize_flags_p (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
 	{
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index ca87b438bd3..43e236de41c 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -822,6 +822,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
   if (decl_maybe_constant_var_p (decl) || TREE_STATIC (decl))
     {
       bool const_init;
+      tree oldval = value;
       value = fold_non_dependent_expr (value);
       if (DECL_DECLARED_CONSTEXPR_P (decl)
 	  || (DECL_IN_AGGR_P (decl)
@@ -847,6 +848,8 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
       /* FIXME setting TREE_CONSTANT on refs breaks the back end.  */
       if (!TYPE_REF_P (type))
 	TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
+      if (!const_init)
+	value = oldval;
     }
   value = cp_fully_fold (value);
 
@@ -899,7 +902,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
       return ok;
     }
 
-  init = fold_non_dependent_expr (init);
+  init = fold_non_dependent_expr (init, complain);
 
   if (TREE_CODE (type) == INTEGER_TYPE
       && TREE_CODE (ftype) == REAL_TYPE)
@@ -1254,7 +1257,7 @@ massage_init_elt (tree type, tree init, int nested, tsubst_flags_t complain)
     init = TARGET_EXPR_INITIAL (init);
   /* When we defer constant folding within a statement, we may want to
      defer this folding as well.  */
-  tree t = fold_non_dependent_expr (init);
+  tree t = fold_non_dependent_expr (init, complain);
   t = maybe_constant_init (t);
   if (TREE_CONSTANT (t))
     init = t;
diff --git a/gcc/testsuite/g++.dg/template/conv15.C b/gcc/testsuite/g++.dg/template/conv15.C
new file mode 100644
index 00000000000..2f61c113564
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/conv15.C
@@ -0,0 +1,10 @@
+// PR c++/86219
+
+template <int a> struct t;
+template <int a>
+void f ()
+{
+   const int b = "";		// { dg-error "conversion" }
+   t<b>::c;			// { dg-error "constant" }
+   // { dg-prune-output "template argument 1 is invalid" }
+}
commit 05e980d2b38d2405448632a92d767eea1eaaa2df
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Jun 22 12:44:43 2018 -0400

            Avoid taking the address of something just because it's in parens.
    
            * constexpr.c (same_type_ignoring_tlq_and_bounds_p): New.
            (cxx_fold_indirect_ref): Use it.
            (cxx_eval_constant_expression) [VIEW_CONVERT_EXPR]: Use it.
            * cp-tree.h (REF_PARENTHESIZED_P): Allow VIEW_CONVERT_EXPR.
            * semantics.c (force_paren_expr): Use VIEW_CONVERT_EXPR instead of
            static_cast to reference type.
            (maybe_undo_parenthesized_ref): Handle VIEW_CONVERT_EXPR.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 44f3093ab47..dea2a4e57b3 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3076,6 +3076,23 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t,
     return r;
 }
 
+/* Like same_type_ignoring_top_level_qualifiers_p, but also handle the case
+   where the desired type is an array of unknown bounds because the variable
+   has had its bounds deduced since the wrapping expression was created.  */
+
+static bool
+same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
+{
+  while (TREE_CODE (type1) == ARRAY_TYPE
+	 && TREE_CODE (type2) == ARRAY_TYPE
+	 && (!TYPE_DOMAIN (type1) || !TYPE_DOMAIN (type2)))
+    {
+      type1 = TREE_TYPE (type1);
+      type2 = TREE_TYPE (type2);
+    }
+  return same_type_ignoring_top_level_qualifiers_p (type1, type2);
+}
+
 /* A less strict version of fold_indirect_ref_1, which requires cv-quals to
    match.  We want to be less strict for simple *& folding; if we have a
    non-const temporary that we access through a const pointer, that should
@@ -3108,15 +3125,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
       if (TREE_CODE (op) == CONST_DECL)
 	return DECL_INITIAL (op);
       /* *&p => p;  make sure to handle *&"str"[cst] here.  */
-      if (same_type_ignoring_top_level_qualifiers_p (optype, type)
-	  /* Also handle the case where the desired type is an array of unknown
-	     bounds because the variable has had its bounds deduced since the
-	     ADDR_EXPR was created.  */
-	  || (TREE_CODE (type) == ARRAY_TYPE
-	      && TREE_CODE (optype) == ARRAY_TYPE
-	      && TYPE_DOMAIN (type) == NULL_TREE
-	      && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (optype),
-							    TREE_TYPE (type))))
+      if (same_type_ignoring_tlq_and_bounds_p (optype, type))
 	{
 	  tree fop = fold_read_from_constant_string (op);
 	  if (fop)
@@ -4676,7 +4685,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	     conversion.  */
 	  return fold (t);
 
-	if (tcode == UNARY_PLUS_EXPR)
+	/* Handle an array's bounds having been deduced after we built
+	   the wrapping expression.  */
+	if (same_type_ignoring_tlq_and_bounds_p (type, TREE_TYPE (op)))
+	  r = op;
+	else if (tcode == UNARY_PLUS_EXPR)
 	  r = fold_convert (TREE_TYPE (t), op);
 	else
 	  r = fold_build1 (tcode, type, op);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e1465a915f1..264bba53f0d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -399,7 +399,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
       FNDECL_USED_AUTO (in FUNCTION_DECL)
       DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
-      REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF)
+      REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR)
       AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR)
       CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR)
       OVL_HIDDEN_P (in OVERLOAD)
@@ -3676,7 +3676,7 @@ struct GTY(()) lang_decl {
    of the time in C++14 mode.  */
 
 #define REF_PARENTHESIZED_P(NODE) \
-  TREE_LANG_FLAG_2 (TREE_CHECK3 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF))
+  TREE_LANG_FLAG_2 (TREE_CHECK4 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR))
 
 /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a
    constructor call, rather than an ordinary function call.  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index bad712ee6e8..da75f30885f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1720,23 +1720,10 @@ force_paren_expr (tree expr)
     REF_PARENTHESIZED_P (expr) = true;
   else if (processing_template_decl)
     expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr);
-  else if (VAR_P (expr) && DECL_HARD_REGISTER (expr))
-    /* We can't bind a hard register variable to a reference.  */;
   else
     {
-      cp_lvalue_kind kind = lvalue_kind (expr);
-      if ((kind & ~clk_class) != clk_none)
-	{
-	  tree type = unlowered_expr_type (expr);
-	  bool rval = !!(kind & clk_rvalueref);
-	  type = cp_build_reference_type (type, rval);
-	  /* This inhibits warnings in, eg, cxx_mark_addressable
-	     (c++/60955).  */
-	  warning_sentinel s (extra_warnings);
-	  expr = build_static_cast (type, expr, tf_error);
-	  if (expr != error_mark_node)
-	    REF_PARENTHESIZED_P (expr) = true;
-	}
+      expr = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+      REF_PARENTHESIZED_P (expr) = true;
     }
 
   return expr;
@@ -1765,6 +1752,9 @@ maybe_undo_parenthesized_ref (tree t)
     }
   else if (TREE_CODE (t) == PAREN_EXPR)
     t = TREE_OPERAND (t, 0);
+  else if (TREE_CODE (t) == VIEW_CONVERT_EXPR
+	   && REF_PARENTHESIZED_P (t))
+    t = TREE_OPERAND (t, 0);
 
   return t;
 }
commit 097a94cc7ae57759e5a52ac30b2d60ea1d306477
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Jun 21 14:54:59 2018 -0400

            PR c++/86219 - ICE with erroneous initializer in template.
    
            * constexpr.c (fold_non_dependent_expr): Add complain parm.
            * typeck2.c (store_init_value): Pass tf_warning_or_error.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index b4bcc6a567d..178026512b4 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -5107,12 +5107,12 @@ clear_cv_and_fold_caches (void)
 /* Like maybe_constant_value but first fully instantiate the argument.
 
    Note: this is equivalent to instantiate_non_dependent_expr_sfinae
-   (t, tf_none) followed by maybe_constant_value but is more efficient,
+   (t, complain) followed by maybe_constant_value but is more efficient,
    because calls instantiation_dependent_expression_p and
    potential_constant_expression at most once.  */
 
 tree
-fold_non_dependent_expr (tree t)
+fold_non_dependent_expr (tree t, tsubst_flags_t complain /* = tf_none */)
 {
   if (t == NULL_TREE)
     return NULL_TREE;
@@ -5129,7 +5129,7 @@ fold_non_dependent_expr (tree t)
       if (is_nondependent_constant_expression (t))
 	{
 	  processing_template_decl_sentinel s;
-	  t = instantiate_non_dependent_expr_internal (t, tf_none);
+	  t = instantiate_non_dependent_expr_internal (t, complain);
 
 	  if (type_unknown_p (t)
 	      || BRACE_ENCLOSED_INITIALIZER_P (t))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7603786576c..85ba5b87e3b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7546,7 +7546,7 @@ extern tree cxx_constant_value			(tree, tree = NULL_TREE);
 extern tree cxx_constant_init			(tree, tree = NULL_TREE);
 extern tree maybe_constant_value		(tree, tree = NULL_TREE);
 extern tree maybe_constant_init			(tree, tree = NULL_TREE);
-extern tree fold_non_dependent_expr		(tree);
+extern tree fold_non_dependent_expr		(tree, tsubst_flags_t = tf_none);
 extern tree fold_simple				(tree);
 extern bool is_sub_constant_expr                (tree);
 extern bool reduced_constant_expression_p       (tree);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 444ebfdcb37..105d128899a 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -822,7 +822,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
   if (decl_maybe_constant_var_p (decl) || TREE_STATIC (decl))
     {
       bool const_init;
-      value = fold_non_dependent_expr (value);
+      value = fold_non_dependent_expr (value, tf_warning_or_error);
       if (DECL_DECLARED_CONSTEXPR_P (decl)
 	  || (DECL_IN_AGGR_P (decl)
 	      && DECL_INITIALIZED_IN_CLASS_P (decl)
diff --git a/gcc/testsuite/g++.dg/template/conv15.C b/gcc/testsuite/g++.dg/template/conv15.C
new file mode 100644
index 00000000000..2f61c113564
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/conv15.C
@@ -0,0 +1,10 @@
+// PR c++/86219
+
+template <int a> struct t;
+template <int a>
+void f ()
+{
+   const int b = "";		// { dg-error "conversion" }
+   t<b>::c;			// { dg-error "constant" }
+   // { dg-prune-output "template argument 1 is invalid" }
+}

Reply via email to