aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-06-22 17:57:07 -0400
committerJason Merrill <jason@gcc.gnu.org>2018-06-22 17:57:07 -0400
commite56f662950ce31be414d64699b369ad9a5aca556 (patch)
tree3c353035edc43d26c7a4f038fcd1cd043b06b82e /gcc
parente4511ca2e9ecdb51d41b64452398f8e2df575668 (diff)
downloadgcc-e56f662950ce31be414d64699b369ad9a5aca556.zip
gcc-e56f662950ce31be414d64699b369ad9a5aca556.tar.gz
gcc-e56f662950ce31be414d64699b369ad9a5aca556.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/constexpr.c18
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/expr.c8
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/pt.c12
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/cp/typeck.c16
-rw-r--r--gcc/cp/typeck2.c7
-rw-r--r--gcc/testsuite/g++.dg/template/conv15.C10
11 files changed, 65 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8c7b19b..ae2fd61 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,13 @@
2018-06-22 Jason Merrill <jason@redhat.com>
+ 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 e417590..aa0e696 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 dea2a4e..365296d 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 f16f00c..284b443 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 133a01b..93477bc 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 810a776..76ce0b8 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 69e9479..e1e2f01 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 da75f30..c779137 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 936de9f..3a4f1cd 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 ca87b43..43e236d 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 0000000..2f61c11
--- /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" }
+}