From: Jason Merrill Date: Fri, 22 Jun 2018 21:57:07 +0000 (-0400) Subject: PR c++/86219 - ICE with erroneous initializer in template. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e56f662950ce31be414d64699b369ad9a5aca556;p=gcc.git 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. From-SVN: r261972 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8c7b19b1754..ae2fd618c19 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2018-06-22 Jason Merrill + 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. + 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. 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 f16f00c40de..284b44343d3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7534,7 +7534,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 **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 **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 69e9479302e..e1e2f0152c1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16863,7 +16863,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)); @@ -16876,7 +16877,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; @@ -18517,7 +18519,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) @@ -22082,7 +22084,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); @@ -25849,7 +25851,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** 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** 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 struct t; +template +void f () +{ + const int b = ""; // { dg-error "conversion" } + t::c; // { dg-error "constant" } + // { dg-prune-output "template argument 1 is invalid" } +}