* [C++ Patch] Add maybe_constant_folded_value @ 2014-11-13 10:54 Paolo Carlini 2014-11-13 16:41 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2014-11-13 10:54 UTC (permalink / raw) To: gcc-patches; +Cc: Jason Merrill [-- Attachment #1: Type: text/plain, Size: 109 bytes --] Hi, shall we do something like the below? Safety checked x86_64-linux. Thanks, Paolo. /////////////////// [-- Attachment #2: CL --] [-- Type: text/plain, Size: 407 bytes --] 2014-11-13 Paolo Carlini <paolo.carlini@oracle.com> * constexpr.c (maybe_constant_folded_value): Add. * cp-tree.h (maybe_constant_folded_value): Declare it. * call.c (null_ptr_cst_p): Use it. * pt.c (tsubst_copy_and_build, build_non_dependent_expr): Likewise. * semantics.c (begin_maybe_infinite_loop): Likewise. * typeck.c (cp_build_binary_op): Likewise. * typeck2.c (check_narrowing): Likewise. [-- Attachment #3: patchlet --] [-- Type: text/plain, Size: 5837 bytes --] Index: call.c =================================================================== --- call.c (revision 217468) +++ call.c (working copy) @@ -572,7 +572,7 @@ null_ptr_cst_p (tree t) { /* Core issue 903 says only literal 0 is a null pointer constant. */ if (cxx_dialect < cxx11) - t = maybe_constant_value (fold_non_dependent_expr_sfinae (t, tf_none)); + t = maybe_constant_folded_value (t); STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; Index: constexpr.c =================================================================== --- constexpr.c (revision 217468) +++ constexpr.c (working copy) @@ -2914,6 +2914,14 @@ maybe_constant_value (tree t, tree decl) return r; } +/* Like maybe_constant_value but first fold the argument. */ + +tree +maybe_constant_folded_value (tree t) +{ + return maybe_constant_value (fold_non_dependent_expr_sfinae (t, tf_none)); +} + /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather than wrapped in a TARGET_EXPR. */ Index: cp-tree.h =================================================================== --- cp-tree.h (revision 217468) +++ cp-tree.h (working copy) @@ -6334,6 +6334,7 @@ extern bool require_potential_rvalue_constant_expr extern tree cxx_constant_value (tree, tree = NULL_TREE); extern tree maybe_constant_value (tree, tree = NULL_TREE); extern tree maybe_constant_init (tree, tree = NULL_TREE); +extern tree maybe_constant_folded_value (tree); extern bool is_sub_constant_expr (tree); extern bool reduced_constant_expression_p (tree); extern bool is_instantiation_of_constexpr (tree); Index: pt.c =================================================================== --- pt.c (revision 217468) +++ pt.c (working copy) @@ -15138,8 +15138,7 @@ tsubst_copy_and_build (tree t, case COND_EXPR: { tree cond = RECUR (TREE_OPERAND (t, 0)); - tree folded_cond = (maybe_constant_value - (fold_non_dependent_expr_sfinae (cond, tf_none))); + tree folded_cond = maybe_constant_folded_value (cond); tree exp1, exp2; if (TREE_CODE (folded_cond) == INTEGER_CST) @@ -21864,7 +21863,7 @@ build_non_dependent_expr (tree expr) /* Try to get a constant value for all non-dependent expressions in order to expose bugs in *_dependent_expression_p and constexpr. */ if (cxx_dialect >= cxx11) - maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none)); + maybe_constant_folded_value (expr); #endif /* Preserve OVERLOADs; the functions must be available to resolve Index: semantics.c =================================================================== --- semantics.c (revision 217468) +++ semantics.c (working copy) @@ -511,8 +511,7 @@ begin_maybe_infinite_loop (tree cond) bool maybe_infinite = true; if (cond) { - cond = fold_non_dependent_expr_sfinae (cond, tf_none); - cond = maybe_constant_value (cond); + cond = maybe_constant_folded_value (cond); maybe_infinite = integer_nonzerop (cond); } vec_safe_push (cp_function_chain->infinite_loops, Index: typeck.c =================================================================== --- typeck.c (revision 217468) +++ typeck.c (working copy) @@ -4133,8 +4133,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_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = maybe_constant_folded_value (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); @@ -4173,8 +4172,7 @@ cp_build_binary_op (location_t location, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: { - tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = maybe_constant_folded_value (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); } @@ -4268,8 +4266,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = maybe_constant_folded_value (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4318,8 +4315,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = maybe_constant_folded_value (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4991,10 +4987,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 = maybe_constant_value (fold_non_dependent_expr_sfinae (op0, - tf_none)); - op1 = maybe_constant_value (fold_non_dependent_expr_sfinae (op1, - tf_none)); + op0 = maybe_constant_folded_value (op0); + op1 = maybe_constant_folded_value (op1); if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))) { Index: typeck2.c =================================================================== --- typeck2.c (revision 217468) +++ typeck2.c (working copy) @@ -872,7 +872,7 @@ check_narrowing (tree type, tree init, tsubst_flag return ok; } - init = maybe_constant_value (fold_non_dependent_expr_sfinae (init, tf_none)); + init = maybe_constant_folded_value (init); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (ftype) == REAL_TYPE) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-13 10:54 [C++ Patch] Add maybe_constant_folded_value Paolo Carlini @ 2014-11-13 16:41 ` Jason Merrill 2014-11-13 16:43 ` Kai Tietz 2014-11-13 16:43 ` Jason Merrill 0 siblings, 2 replies; 10+ messages in thread From: Jason Merrill @ 2014-11-13 16:41 UTC (permalink / raw) To: Paolo Carlini, gcc-patches, Tietz, Kai On 11/13/2014 05:47 AM, Paolo Carlini wrote: > shall we do something like the below? Something similar, yes. Though it would also be nice to avoid the redundant checking in the two functions: we only want to do constexpr folding if we did the tsubst. Kai is working on folding changes, so I think let's let him weigh in on how this will interact with his work. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-13 16:41 ` Jason Merrill @ 2014-11-13 16:43 ` Kai Tietz 2014-11-13 16:43 ` Jason Merrill 1 sibling, 0 replies; 10+ messages in thread From: Kai Tietz @ 2014-11-13 16:43 UTC (permalink / raw) To: Jason Merrill; +Cc: Paolo Carlini, gcc-patches, Tietz, Kai 2014-11-13 17:10 GMT+01:00 Jason Merrill <jason@redhat.com>: > On 11/13/2014 05:47 AM, Paolo Carlini wrote: >> >> shall we do something like the below? > > > Something similar, yes. Though it would also be nice to avoid the redundant > checking in the two functions: we only want to do constexpr folding if we > did the tsubst. > > Kai is working on folding changes, so I think let's let him weigh in on how > this will interact with his work. > > Jason > So far this patch shouldn't interact to my work so far. Having such a function is nice. This redundant checking is indeed a bit backward as it can cost. Kai ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-13 16:41 ` Jason Merrill 2014-11-13 16:43 ` Kai Tietz @ 2014-11-13 16:43 ` Jason Merrill 2014-11-13 17:50 ` Paolo Carlini 1 sibling, 1 reply; 10+ messages in thread From: Jason Merrill @ 2014-11-13 16:43 UTC (permalink / raw) To: Paolo Carlini, gcc-patches, Tietz, Kai On 11/13/2014 11:10 AM, Jason Merrill wrote: > On 11/13/2014 05:47 AM, Paolo Carlini wrote: >> shall we do something like the below? > > Something similar, yes. Though it would also be nice to avoid the > redundant checking in the two functions: we only want to do constexpr > folding if we did the tsubst. > > Kai is working on folding changes, so I think let's let him weigh in on > how this will interact with his work. Kai says this is fine with him. I think I'd like to rename the current fold_non_dependent_expr* to instantiate_non_dependent_expr* and make your new function fold_non_dependent_expr, since it's the one that's doing full constant folding. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-13 16:43 ` Jason Merrill @ 2014-11-13 17:50 ` Paolo Carlini 2014-11-13 18:40 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2014-11-13 17:50 UTC (permalink / raw) To: Jason Merrill, gcc-patches, Tietz, Kai [-- Attachment #1: Type: text/plain, Size: 1055 bytes --] Hi, On 11/13/2014 05:42 PM, Jason Merrill wrote: > On 11/13/2014 11:10 AM, Jason Merrill wrote: >> On 11/13/2014 05:47 AM, Paolo Carlini wrote: >>> shall we do something like the below? >> >> Something similar, yes. Though it would also be nice to avoid the >> redundant checking in the two functions: we only want to do constexpr >> folding if we did the tsubst. >> >> Kai is working on folding changes, so I think let's let him weigh in on >> how this will interact with his work. > > Kai says this is fine with him. I think I'd like to rename the > current fold_non_dependent_expr* to instantiate_non_dependent_expr* > and make your new function fold_non_dependent_expr, since it's the one > that's doing full constant folding. Good. Then I'm finishing sanity checking the below. While we are at it, can you double check that in end_maybe_infinite_loop we really want the non-sfinae version (which in principle can emit hard errors): the inconsistency with begin_maybe_infinite_loop seems weird to me... Thanks! Paolo. //////////////////// [-- Attachment #2: CL2 --] [-- Type: text/plain, Size: 1103 bytes --] 2014-11-13 Paolo Carlini <paolo.carlini@oracle.com> * constexpr.c (fold_non_dependent_expr): Add. * cp-tree.h (fold_non_dependent_expr): Declare it. * call.c (null_ptr_cst_p): Use it. * pt.c (tsubst_copy_and_build, build_non_dependent_expr): Likewise. * semantics.c (begin_maybe_infinite_loop): Likewise. * typeck.c (cp_build_binary_op): Likewise. * typeck2.c (check_narrowing): Likewise. * pt.c (fold_non_dependent_expr): Rename to instantiate_non_dependent_expr. (fold_non_dependent_expr_sfinae): Rename to instantiate_non_dependent_expr_sfinae. (convert_nontype_argument, build_non_dependent_expr): Adjust. * decl.c (compute_array_index_type): Likewise. * parser.c (cp_parser_parenthesized_expression_list, cp_parser_enumerator_definition, cp_parser_omp_clause_collapse): Likewise. * semantics.c (end_maybe_infinite_loop, finish_static_assert): Likewise. * typeck.c (cxx_alignas_expr): Likewise. * typeck2.c (store_init_value, massage_init_elt): Likewise. * call.c: Adjust comments. * class.c: Likewise. * constexpr.c: Likewise. * decl2.c: Likewise. * tree.c: Likewise. [-- Attachment #3: patchlet2 --] [-- Type: text/plain, Size: 15474 bytes --] Index: call.c =================================================================== --- call.c (revision 217503) +++ call.c (working copy) @@ -572,7 +572,7 @@ null_ptr_cst_p (tree t) { /* Core issue 903 says only literal 0 is a null pointer constant. */ if (cxx_dialect < cxx11) - t = maybe_constant_value (fold_non_dependent_expr_sfinae (t, tf_none)); + t = fold_non_dependent_expr (t); STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; @@ -7437,8 +7437,8 @@ build_over_call (struct z_candidate *cand, int fla return error_mark_node; if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0 - /* Don't mess with virtual lookup in fold_non_dependent_expr; virtual - functions can't be constexpr. */ + /* Don't mess with virtual lookup in instantiate_non_dependent_expr; + virtual functions can't be constexpr. */ && !in_template_function ()) { tree t; @@ -9361,7 +9361,7 @@ perform_implicit_conversion_flags (tree type, tree type of non-dependent expressions, so we do not have to perform the actual conversion. But for initializers, we need to be able to perform it at instantiation - (or fold_non_dependent_expr) time. */ + (or instantiate_non_dependent_expr) time. */ expr = build1 (IMPLICIT_CONV_EXPR, type, expr); if (!(flags & LOOKUP_ONLYCONVERTING)) IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true; Index: class.c =================================================================== --- class.c (revision 217503) +++ class.c (working copy) @@ -359,9 +359,9 @@ build_base_path (enum tree_code code, /* Don't bother with the calculations inside sizeof; they'll ICE if the source type is incomplete and the pointer value doesn't matter. In a - template (even in fold_non_dependent_expr), we don't have vtables set - up properly yet, and the value doesn't matter there either; we're just - interested in the result of overload resolution. */ + template (even in instantiate_non_dependent_expr), we don't have vtables + set up properly yet, and the value doesn't matter there either; we're + just interested in the result of overload resolution. */ if (cp_unevaluated_operand != 0 || in_template_function ()) { @@ -6933,7 +6933,8 @@ resolves_to_fixed_type_p (tree instance, int* nonn tree fixed; /* processing_template_decl can be false in a template if we're in - fold_non_dependent_expr, but we still want to suppress this check. */ + instantiate_non_dependent_expr, but we still want to suppress + this check. */ if (in_template_function ()) { /* In a template we only care about the type of the result. */ Index: constexpr.c =================================================================== --- constexpr.c (revision 217503) +++ constexpr.c (working copy) @@ -2914,6 +2914,15 @@ maybe_constant_value (tree t, tree decl) return r; } +/* Like maybe_constant_value but first fully constant fold the argument. */ + +tree +fold_non_dependent_expr (tree t) +{ + return (maybe_constant_value + (instantiate_non_dependent_expr_sfinae (t, tf_none))); +} + /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather than wrapped in a TARGET_EXPR. */ @@ -3386,7 +3395,7 @@ potential_constant_expression_1 (tree t, bool want if (!potential_constant_expression_1 (denom, rval, flags)) return false; /* We can't call cxx_eval_outermost_constant_expr on an expression - that hasn't been through fold_non_dependent_expr yet. */ + that hasn't been through instantiate_non_dependent_expr yet. */ if (!processing_template_decl) denom = cxx_eval_outermost_constant_expr (denom, true); if (integer_zerop (denom)) Index: cp-tree.h =================================================================== --- cp-tree.h (revision 217503) +++ cp-tree.h (working copy) @@ -5690,8 +5690,8 @@ extern tree template_for_substitution (tree); extern tree build_non_dependent_expr (tree); extern void make_args_non_dependent (vec<tree, va_gc> *); extern bool reregister_specialization (tree, tree, tree); -extern tree fold_non_dependent_expr (tree); -extern tree fold_non_dependent_expr_sfinae (tree, tsubst_flags_t); +extern tree instantiate_non_dependent_expr (tree); +extern tree instantiate_non_dependent_expr_sfinae (tree, tsubst_flags_t); extern bool alias_type_or_template_p (tree); extern bool alias_template_specialization_p (const_tree); extern bool dependent_alias_template_spec_p (const_tree); @@ -6331,6 +6331,7 @@ extern bool require_potential_rvalue_constant_expr extern tree cxx_constant_value (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 bool is_sub_constant_expr (tree); extern bool reduced_constant_expression_p (tree); extern bool is_instantiation_of_constexpr (tree); Index: decl.c =================================================================== --- decl.c (revision 217503) +++ decl.c (working copy) @@ -8356,7 +8356,7 @@ compute_array_index_type (tree name, tree size, ts NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */; else { - size = fold_non_dependent_expr_sfinae (size, complain); + size = instantiate_non_dependent_expr_sfinae (size, complain); if (CLASS_TYPE_P (type) && CLASSTYPE_LITERAL_P (type)) Index: decl2.c =================================================================== --- decl2.c (revision 217503) +++ decl2.c (working copy) @@ -4951,7 +4951,7 @@ mark_used (tree decl, tsubst_flags_t complain) if (processing_template_decl) return true; - /* Check this too in case we're within fold_non_dependent_expr. */ + /* Check this too in case we're within instantiate_non_dependent_expr. */ if (DECL_TEMPLATE_INFO (decl) && uses_template_parms (DECL_TI_ARGS (decl))) return true; Index: parser.c =================================================================== --- parser.c (revision 217503) +++ parser.c (working copy) @@ -6886,7 +6886,7 @@ cp_parser_parenthesized_expression_list (cp_parser } if (fold_expr_p) - expr = fold_non_dependent_expr (expr); + expr = instantiate_non_dependent_expr (expr); /* If we have an ellipsis, then this is an expression expansion. */ @@ -15998,7 +15998,7 @@ cp_parser_enumerator_definition (cp_parser* parser /* integral_constant_value will pull out this expression, so make sure it's folded as appropriate. */ - value = fold_non_dependent_expr (value); + value = instantiate_non_dependent_expr (value); /* Create the enumerator. */ build_enumerator (identifier, value, type, loc); @@ -27724,7 +27724,7 @@ cp_parser_omp_clause_collapse (cp_parser *parser, if (num == error_mark_node) return list; - num = fold_non_dependent_expr (num); + num = instantiate_non_dependent_expr (num); if (!INTEGRAL_TYPE_P (TREE_TYPE (num)) || !tree_fits_shwi_p (num) || (n = tree_to_shwi (num)) <= 0 Index: pt.c =================================================================== --- pt.c (revision 217503) +++ pt.c (working copy) @@ -5216,7 +5216,7 @@ redeclare_class_template (tree type, tree parms) (possibly simplified) expression. */ tree -fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) +instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) { if (expr == NULL_TREE) return NULL_TREE; @@ -5248,9 +5248,9 @@ tree } tree -fold_non_dependent_expr (tree expr) +instantiate_non_dependent_expr (tree expr) { - return fold_non_dependent_expr_sfinae (expr, tf_error); + return instantiate_non_dependent_expr_sfinae (expr, tf_error); } /* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias @@ -5740,7 +5740,7 @@ convert_nontype_argument (tree type, tree expr, ts && has_value_dependent_address (expr)) /* If we want the address and it's value-dependent, don't fold. */; else if (!type_unknown_p (expr)) - expr = fold_non_dependent_expr_sfinae (expr, complain); + expr = instantiate_non_dependent_expr_sfinae (expr, complain); if (error_operand_p (expr)) return error_mark_node; expr_type = TREE_TYPE (expr); @@ -8314,7 +8314,7 @@ uses_template_parms (tree t) /* Returns true iff current_function_decl is an incompletely instantiated template. Useful instead of processing_template_decl because the latter - is set to 0 during fold_non_dependent_expr. */ + is set to 0 during instantiate_non_dependent_expr. */ bool in_template_function (void) @@ -15138,8 +15138,7 @@ tsubst_copy_and_build (tree t, case COND_EXPR: { tree cond = RECUR (TREE_OPERAND (t, 0)); - tree folded_cond = (maybe_constant_value - (fold_non_dependent_expr_sfinae (cond, tf_none))); + tree folded_cond = fold_non_dependent_expr (cond); tree exp1, exp2; if (TREE_CODE (folded_cond) == INTEGER_CST) @@ -21110,7 +21109,7 @@ value_dependent_expression_p (tree expression) case STMT_EXPR: /* Treat a GNU statement expression as dependent to avoid crashing - under fold_non_dependent_expr; it can't be constant. */ + under instantiate_non_dependent_expr; it can't be constant. */ return true; default: @@ -21864,7 +21863,7 @@ build_non_dependent_expr (tree expr) /* Try to get a constant value for all non-dependent expressions in order to expose bugs in *_dependent_expression_p and constexpr. */ if (cxx_dialect >= cxx11) - maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none)); + fold_non_dependent_expr (expr); #endif /* Preserve OVERLOADs; the functions must be available to resolve Index: semantics.c =================================================================== --- semantics.c (revision 217503) +++ semantics.c (working copy) @@ -511,8 +511,7 @@ begin_maybe_infinite_loop (tree cond) bool maybe_infinite = true; if (cond) { - cond = fold_non_dependent_expr_sfinae (cond, tf_none); - cond = maybe_constant_value (cond); + cond = fold_non_dependent_expr (cond); maybe_infinite = integer_nonzerop (cond); } vec_safe_push (cp_function_chain->infinite_loops, @@ -542,7 +541,7 @@ end_maybe_infinite_loop (tree cond) tree current = cp_function_chain->infinite_loops->pop(); if (current != NULL_TREE) { - cond = fold_non_dependent_expr (cond); + cond = instantiate_non_dependent_expr (cond); cond = maybe_constant_value (cond); if (integer_nonzerop (cond)) current_function_infinite_loop = 1; @@ -7043,7 +7042,7 @@ finish_static_assert (tree condition, tree message } /* Fold the expression and convert it to a boolean value. */ - condition = fold_non_dependent_expr (condition); + condition = instantiate_non_dependent_expr (condition); condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); Index: tree.c =================================================================== --- tree.c (revision 217503) +++ tree.c (working copy) @@ -4143,7 +4143,7 @@ fold_if_not_in_template (tree expr) /* In the body of a template, there is never any need to call "fold". We will call fold later when actually instantiating the template. Integral constant expressions in templates will be - evaluated via fold_non_dependent_expr, as necessary. */ + evaluated via instantiate_non_dependent_expr, as necessary. */ if (processing_template_decl) return expr; Index: typeck.c =================================================================== --- typeck.c (revision 217503) +++ typeck.c (working copy) @@ -1787,7 +1787,7 @@ cxx_alignas_expr (tree e) /* Leave value-dependent expression alone for now. */ return e; - e = fold_non_dependent_expr (e); + e = instantiate_non_dependent_expr (e); e = mark_rvalue_use (e); /* [dcl.align]/2 says: @@ -4135,8 +4135,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_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = fold_non_dependent_expr (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); @@ -4175,8 +4174,7 @@ cp_build_binary_op (location_t location, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: { - tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = fold_non_dependent_expr (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); } @@ -4270,8 +4268,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = fold_non_dependent_expr (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4320,8 +4317,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = fold_non_dependent_expr (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4993,10 +4989,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 = maybe_constant_value (fold_non_dependent_expr_sfinae (op0, - tf_none)); - op1 = maybe_constant_value (fold_non_dependent_expr_sfinae (op1, - tf_none)); + op0 = fold_non_dependent_expr (op0); + op1 = fold_non_dependent_expr (op1); if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))) { Index: typeck2.c =================================================================== --- typeck2.c (revision 217503) +++ typeck2.c (working copy) @@ -797,7 +797,7 @@ store_init_value (tree decl, tree init, vec<tree, if (decl_maybe_constant_var_p (decl) || TREE_STATIC (decl)) { bool const_init; - value = fold_non_dependent_expr (value); + value = instantiate_non_dependent_expr (value); if (DECL_DECLARED_CONSTEXPR_P (decl) || DECL_IN_AGGR_P (decl)) { @@ -872,7 +872,7 @@ check_narrowing (tree type, tree init, tsubst_flag return ok; } - init = maybe_constant_value (fold_non_dependent_expr_sfinae (init, tf_none)); + init = fold_non_dependent_expr (init); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (ftype) == REAL_TYPE) @@ -1176,7 +1176,7 @@ massage_init_elt (tree type, tree init, tsubst_fla 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_sfinae (init, complain); + tree t = instantiate_non_dependent_expr_sfinae (init, complain); t = maybe_constant_init (t); if (TREE_CONSTANT (t)) init = t; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-13 17:50 ` Paolo Carlini @ 2014-11-13 18:40 ` Jason Merrill 2014-11-13 21:45 ` Paolo Carlini 0 siblings, 1 reply; 10+ messages in thread From: Jason Merrill @ 2014-11-13 18:40 UTC (permalink / raw) To: Paolo Carlini, gcc-patches, Tietz, Kai On 11/13/2014 12:48 PM, Paolo Carlini wrote: > While we are at it, can you double check that in end_maybe_infinite_loop > we really want the non-sfinae version (which in principle can emit hard > errors): the inconsistency with begin_maybe_infinite_loop seems weird to > me... I agree, let's use the sfinae version there too. > @@ -15998,7 +15998,7 @@ cp_parser_enumerator_definition (cp_parser* parser > > /* integral_constant_value will pull out this expression, so make sure > it's folded as appropriate. */ > - value = fold_non_dependent_expr (value); > + value = instantiate_non_dependent_expr (value); I think this should be replaced with fold_ if (processing_template_decl) in build_enumerator. > @@ -27724,7 +27724,7 @@ cp_parser_omp_clause_collapse (cp_parser *parser, > > if (num == error_mark_node) > return list; > - num = fold_non_dependent_expr (num); > + num = instantiate_non_dependent_expr (num); I think we want fold_ here. > /* When we defer constant folding within a statement, we may want to > defer this folding as well. */ > - tree t = fold_non_dependent_expr_sfinae (init, complain); > + tree t = instantiate_non_dependent_expr_sfinae (init, complain); > t = maybe_constant_init (t); Let's use it here, too. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-13 18:40 ` Jason Merrill @ 2014-11-13 21:45 ` Paolo Carlini 2014-11-14 4:25 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2014-11-13 21:45 UTC (permalink / raw) To: Jason Merrill, gcc-patches, Tietz, Kai [-- Attachment #1: Type: text/plain, Size: 2172 bytes --] Hi, On 11/13/2014 07:31 PM, Jason Merrill wrote: > On 11/13/2014 12:48 PM, Paolo Carlini wrote: >> While we are at it, can you double check that in end_maybe_infinite_loop >> we really want the non-sfinae version (which in principle can emit hard >> errors): the inconsistency with begin_maybe_infinite_loop seems weird to >> me... > > I agree, let's use the sfinae version there too. Ok. > >> @@ -15998,7 +15998,7 @@ cp_parser_enumerator_definition (cp_parser* >> parser >> >> /* integral_constant_value will pull out this expression, so make >> sure >> it's folded as appropriate. */ >> - value = fold_non_dependent_expr (value); >> + value = instantiate_non_dependent_expr (value); > > I think this should be replaced with fold_ if > (processing_template_decl) in build_enumerator. Ok. The value can be NULL_TREE, thus in a straightforward change (per the below) I have to check for that, otherwise we crash in maybe_constant_value. Either that or just check for NULL_TREE at the beginning of maybe_constant_value itself, I guess. > @@ -27724,7 +27724,7 @@ cp_parser_omp_clause_collapse (cp_parser *parser, >> >> if (num == error_mark_node) >> return list; >> - num = fold_non_dependent_expr (num); >> + num = instantiate_non_dependent_expr (num); > > I think we want fold_ here. Ok. > >> /* When we defer constant folding within a statement, we may want to >> defer this folding as well. */ >> - tree t = fold_non_dependent_expr_sfinae (init, complain); >> + tree t = instantiate_non_dependent_expr_sfinae (init, complain); >> t = maybe_constant_init (t); > > Let's use it here, too. This is the relatively most tricky change: we have a regression for init/array11.C, because the gcc_assert at the end of maybe_constant_value (called by maybe_constant_init) triggers: gcc_assert (r == t || CONVERT_EXPR_P (t) || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) || !cp_tree_equal (r, t)); we have VIEW_CONVERT_EXPRs, neither is constant, r != t and cp_tree_equal is true. Wild guess: are VIEW_CONVERT_EXPRs also Ok? I'm attaching what I have so far. Thanks, Paolo. ///////////////////// [-- Attachment #2: patchlet3 --] [-- Type: text/plain, Size: 15531 bytes --] Index: call.c =================================================================== --- call.c (revision 217503) +++ call.c (working copy) @@ -572,7 +572,7 @@ null_ptr_cst_p (tree t) { /* Core issue 903 says only literal 0 is a null pointer constant. */ if (cxx_dialect < cxx11) - t = maybe_constant_value (fold_non_dependent_expr_sfinae (t, tf_none)); + t = fold_non_dependent_expr (t); STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; @@ -7437,8 +7437,8 @@ build_over_call (struct z_candidate *cand, int fla return error_mark_node; if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0 - /* Don't mess with virtual lookup in fold_non_dependent_expr; virtual - functions can't be constexpr. */ + /* Don't mess with virtual lookup in instantiate_non_dependent_expr; + virtual functions can't be constexpr. */ && !in_template_function ()) { tree t; @@ -9361,7 +9361,7 @@ perform_implicit_conversion_flags (tree type, tree type of non-dependent expressions, so we do not have to perform the actual conversion. But for initializers, we need to be able to perform it at instantiation - (or fold_non_dependent_expr) time. */ + (or instantiate_non_dependent_expr) time. */ expr = build1 (IMPLICIT_CONV_EXPR, type, expr); if (!(flags & LOOKUP_ONLYCONVERTING)) IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true; Index: class.c =================================================================== --- class.c (revision 217503) +++ class.c (working copy) @@ -359,9 +359,9 @@ build_base_path (enum tree_code code, /* Don't bother with the calculations inside sizeof; they'll ICE if the source type is incomplete and the pointer value doesn't matter. In a - template (even in fold_non_dependent_expr), we don't have vtables set - up properly yet, and the value doesn't matter there either; we're just - interested in the result of overload resolution. */ + template (even in instantiate_non_dependent_expr), we don't have vtables + set up properly yet, and the value doesn't matter there either; we're + just interested in the result of overload resolution. */ if (cp_unevaluated_operand != 0 || in_template_function ()) { @@ -6933,7 +6933,8 @@ resolves_to_fixed_type_p (tree instance, int* nonn tree fixed; /* processing_template_decl can be false in a template if we're in - fold_non_dependent_expr, but we still want to suppress this check. */ + instantiate_non_dependent_expr, but we still want to suppress + this check. */ if (in_template_function ()) { /* In a template we only care about the type of the result. */ Index: constexpr.c =================================================================== --- constexpr.c (revision 217503) +++ constexpr.c (working copy) @@ -2914,6 +2914,15 @@ maybe_constant_value (tree t, tree decl) return r; } +/* Like maybe_constant_value but first fully constant fold the argument. */ + +tree +fold_non_dependent_expr (tree t) +{ + return (maybe_constant_value + (instantiate_non_dependent_expr_sfinae (t, tf_none))); +} + /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather than wrapped in a TARGET_EXPR. */ @@ -3386,7 +3395,7 @@ potential_constant_expression_1 (tree t, bool want if (!potential_constant_expression_1 (denom, rval, flags)) return false; /* We can't call cxx_eval_outermost_constant_expr on an expression - that hasn't been through fold_non_dependent_expr yet. */ + that hasn't been through instantiate_non_dependent_expr yet. */ if (!processing_template_decl) denom = cxx_eval_outermost_constant_expr (denom, true); if (integer_zerop (denom)) Index: cp-tree.h =================================================================== --- cp-tree.h (revision 217503) +++ cp-tree.h (working copy) @@ -5690,8 +5690,8 @@ extern tree template_for_substitution (tree); extern tree build_non_dependent_expr (tree); extern void make_args_non_dependent (vec<tree, va_gc> *); extern bool reregister_specialization (tree, tree, tree); -extern tree fold_non_dependent_expr (tree); -extern tree fold_non_dependent_expr_sfinae (tree, tsubst_flags_t); +extern tree instantiate_non_dependent_expr (tree); +extern tree instantiate_non_dependent_expr_sfinae (tree, tsubst_flags_t); extern bool alias_type_or_template_p (tree); extern bool alias_template_specialization_p (const_tree); extern bool dependent_alias_template_spec_p (const_tree); @@ -6331,6 +6331,7 @@ extern bool require_potential_rvalue_constant_expr extern tree cxx_constant_value (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 bool is_sub_constant_expr (tree); extern bool reduced_constant_expression_p (tree); extern bool is_instantiation_of_constexpr (tree); Index: decl.c =================================================================== --- decl.c (revision 217503) +++ decl.c (working copy) @@ -8356,7 +8356,7 @@ compute_array_index_type (tree name, tree size, ts NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */; else { - size = fold_non_dependent_expr_sfinae (size, complain); + size = instantiate_non_dependent_expr_sfinae (size, complain); if (CLASS_TYPE_P (type) && CLASSTYPE_LITERAL_P (type)) @@ -12999,6 +12999,11 @@ build_enumerator (tree name, tree value, tree enum tree context; tree type; + /* integral_constant_value will pull out this expression, so make sure + it's folded as appropriate. */ + if (processing_template_decl && value) + value = fold_non_dependent_expr (value); + /* If the VALUE was erroneous, pretend it wasn't there; that will result in the enum being assigned the next value in sequence. */ if (value == error_mark_node) Index: decl2.c =================================================================== --- decl2.c (revision 217503) +++ decl2.c (working copy) @@ -4951,7 +4951,7 @@ mark_used (tree decl, tsubst_flags_t complain) if (processing_template_decl) return true; - /* Check this too in case we're within fold_non_dependent_expr. */ + /* Check this too in case we're within instantiate_non_dependent_expr. */ if (DECL_TEMPLATE_INFO (decl) && uses_template_parms (DECL_TI_ARGS (decl))) return true; Index: parser.c =================================================================== --- parser.c (revision 217503) +++ parser.c (working copy) @@ -6886,7 +6886,7 @@ cp_parser_parenthesized_expression_list (cp_parser } if (fold_expr_p) - expr = fold_non_dependent_expr (expr); + expr = instantiate_non_dependent_expr (expr); /* If we have an ellipsis, then this is an expression expansion. */ @@ -15996,10 +15996,6 @@ cp_parser_enumerator_definition (cp_parser* parser if (check_for_bare_parameter_packs (value)) value = error_mark_node; - /* integral_constant_value will pull out this expression, so make sure - it's folded as appropriate. */ - value = fold_non_dependent_expr (value); - /* Create the enumerator. */ build_enumerator (identifier, value, type, loc); } Index: pt.c =================================================================== --- pt.c (revision 217503) +++ pt.c (working copy) @@ -5216,7 +5216,7 @@ redeclare_class_template (tree type, tree parms) (possibly simplified) expression. */ tree -fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) +instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) { if (expr == NULL_TREE) return NULL_TREE; @@ -5248,9 +5248,9 @@ tree } tree -fold_non_dependent_expr (tree expr) +instantiate_non_dependent_expr (tree expr) { - return fold_non_dependent_expr_sfinae (expr, tf_error); + return instantiate_non_dependent_expr_sfinae (expr, tf_error); } /* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias @@ -5740,7 +5740,7 @@ convert_nontype_argument (tree type, tree expr, ts && has_value_dependent_address (expr)) /* If we want the address and it's value-dependent, don't fold. */; else if (!type_unknown_p (expr)) - expr = fold_non_dependent_expr_sfinae (expr, complain); + expr = instantiate_non_dependent_expr_sfinae (expr, complain); if (error_operand_p (expr)) return error_mark_node; expr_type = TREE_TYPE (expr); @@ -8314,7 +8314,7 @@ uses_template_parms (tree t) /* Returns true iff current_function_decl is an incompletely instantiated template. Useful instead of processing_template_decl because the latter - is set to 0 during fold_non_dependent_expr. */ + is set to 0 during instantiate_non_dependent_expr. */ bool in_template_function (void) @@ -15138,8 +15138,7 @@ tsubst_copy_and_build (tree t, case COND_EXPR: { tree cond = RECUR (TREE_OPERAND (t, 0)); - tree folded_cond = (maybe_constant_value - (fold_non_dependent_expr_sfinae (cond, tf_none))); + tree folded_cond = fold_non_dependent_expr (cond); tree exp1, exp2; if (TREE_CODE (folded_cond) == INTEGER_CST) @@ -21110,7 +21109,7 @@ value_dependent_expression_p (tree expression) case STMT_EXPR: /* Treat a GNU statement expression as dependent to avoid crashing - under fold_non_dependent_expr; it can't be constant. */ + under instantiate_non_dependent_expr; it can't be constant. */ return true; default: @@ -21864,7 +21863,7 @@ build_non_dependent_expr (tree expr) /* Try to get a constant value for all non-dependent expressions in order to expose bugs in *_dependent_expression_p and constexpr. */ if (cxx_dialect >= cxx11) - maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none)); + fold_non_dependent_expr (expr); #endif /* Preserve OVERLOADs; the functions must be available to resolve Index: semantics.c =================================================================== --- semantics.c (revision 217503) +++ semantics.c (working copy) @@ -511,8 +511,7 @@ begin_maybe_infinite_loop (tree cond) bool maybe_infinite = true; if (cond) { - cond = fold_non_dependent_expr_sfinae (cond, tf_none); - cond = maybe_constant_value (cond); + cond = fold_non_dependent_expr (cond); maybe_infinite = integer_nonzerop (cond); } vec_safe_push (cp_function_chain->infinite_loops, @@ -543,7 +542,6 @@ end_maybe_infinite_loop (tree cond) if (current != NULL_TREE) { cond = fold_non_dependent_expr (cond); - cond = maybe_constant_value (cond); if (integer_nonzerop (cond)) current_function_infinite_loop = 1; } @@ -7043,7 +7041,7 @@ finish_static_assert (tree condition, tree message } /* Fold the expression and convert it to a boolean value. */ - condition = fold_non_dependent_expr (condition); + condition = instantiate_non_dependent_expr (condition); condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); Index: tree.c =================================================================== --- tree.c (revision 217503) +++ tree.c (working copy) @@ -4143,7 +4143,7 @@ fold_if_not_in_template (tree expr) /* In the body of a template, there is never any need to call "fold". We will call fold later when actually instantiating the template. Integral constant expressions in templates will be - evaluated via fold_non_dependent_expr, as necessary. */ + evaluated via instantiate_non_dependent_expr, as necessary. */ if (processing_template_decl) return expr; Index: typeck.c =================================================================== --- typeck.c (revision 217503) +++ typeck.c (working copy) @@ -1787,7 +1787,7 @@ cxx_alignas_expr (tree e) /* Leave value-dependent expression alone for now. */ return e; - e = fold_non_dependent_expr (e); + e = instantiate_non_dependent_expr (e); e = mark_rvalue_use (e); /* [dcl.align]/2 says: @@ -4135,8 +4135,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_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = fold_non_dependent_expr (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); @@ -4175,8 +4174,7 @@ cp_build_binary_op (location_t location, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: { - tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = fold_non_dependent_expr (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); } @@ -4270,8 +4268,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = fold_non_dependent_expr (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4320,8 +4317,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = fold_non_dependent_expr (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4993,10 +4989,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 = maybe_constant_value (fold_non_dependent_expr_sfinae (op0, - tf_none)); - op1 = maybe_constant_value (fold_non_dependent_expr_sfinae (op1, - tf_none)); + op0 = fold_non_dependent_expr (op0); + op1 = fold_non_dependent_expr (op1); if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))) { Index: typeck2.c =================================================================== --- typeck2.c (revision 217503) +++ typeck2.c (working copy) @@ -797,7 +797,7 @@ store_init_value (tree decl, tree init, vec<tree, if (decl_maybe_constant_var_p (decl) || TREE_STATIC (decl)) { bool const_init; - value = fold_non_dependent_expr (value); + value = instantiate_non_dependent_expr (value); if (DECL_DECLARED_CONSTEXPR_P (decl) || DECL_IN_AGGR_P (decl)) { @@ -872,7 +872,7 @@ check_narrowing (tree type, tree init, tsubst_flag return ok; } - init = maybe_constant_value (fold_non_dependent_expr_sfinae (init, tf_none)); + init = fold_non_dependent_expr (init); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (ftype) == REAL_TYPE) @@ -1176,7 +1176,7 @@ massage_init_elt (tree type, tree init, tsubst_fla 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_sfinae (init, complain); + tree t = fold_non_dependent_expr (init); t = maybe_constant_init (t); if (TREE_CONSTANT (t)) init = t; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-13 21:45 ` Paolo Carlini @ 2014-11-14 4:25 ` Jason Merrill 2014-11-14 14:06 ` Paolo Carlini 0 siblings, 1 reply; 10+ messages in thread From: Jason Merrill @ 2014-11-14 4:25 UTC (permalink / raw) To: Paolo Carlini, gcc-patches, Tietz, Kai On 11/13/2014 04:31 PM, Paolo Carlini wrote: >> I think this should be replaced with fold_ if >> (processing_template_decl) in build_enumerator. > Ok. The value can be NULL_TREE, thus in a straightforward change (per > the below) I have to check for that, otherwise we crash in > maybe_constant_value. Either that or just check for NULL_TREE at the > beginning of maybe_constant_value itself, I guess. The current fold_ already checks for NULL_TREE; I think we want to preserve that behavior. > This is the relatively most tricky change: we have a regression for > init/array11.C, because the gcc_assert at the end of > maybe_constant_value (called by maybe_constant_init) triggers: > > gcc_assert (r == t > || CONVERT_EXPR_P (t) > || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) > || !cp_tree_equal (r, t)); > > we have VIEW_CONVERT_EXPRs, neither is constant, r != t and > cp_tree_equal is true. Wild guess: are VIEW_CONVERT_EXPRs also Ok? Yes. What did you think about avoiding the duplicate instantiation_dependent_expression_p and potential_constant_expression checks? Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-14 4:25 ` Jason Merrill @ 2014-11-14 14:06 ` Paolo Carlini 2014-11-14 14:09 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2014-11-14 14:06 UTC (permalink / raw) To: Jason Merrill, gcc-patches, Tietz, Kai [-- Attachment #1: Type: text/plain, Size: 1983 bytes --] Hi, On 11/14/2014 03:35 AM, Jason Merrill wrote: > On 11/13/2014 04:31 PM, Paolo Carlini wrote: >>> I think this should be replaced with fold_ if >>> (processing_template_decl) in build_enumerator. >> Ok. The value can be NULL_TREE, thus in a straightforward change (per >> the below) I have to check for that, otherwise we crash in >> maybe_constant_value. Either that or just check for NULL_TREE at the >> beginning of maybe_constant_value itself, I guess. > > The current fold_ already checks for NULL_TREE; I think we want to > preserve that behavior. Ok, I added it to the new fold_. > >> This is the relatively most tricky change: we have a regression for >> init/array11.C, because the gcc_assert at the end of >> maybe_constant_value (called by maybe_constant_init) triggers: >> >> gcc_assert (r == t >> || CONVERT_EXPR_P (t) >> || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) >> || !cp_tree_equal (r, t)); >> >> we have VIEW_CONVERT_EXPRs, neither is constant, r != t and >> cp_tree_equal is true. Wild guess: are VIEW_CONVERT_EXPRs also Ok? > > Yes. Ok. > What did you think about avoiding the duplicate > instantiation_dependent_expression_p and potential_constant_expression > checks? Frankly at some point I forgot that, sorry. Today I figured out the below: the new fold_non_dependent_expr is much bigger but definitely calls instantiation_dependent_expression_p and potential_constant_expression at most once and should be always logically equivalent to instantiate_non_dependent_expr_sfinae followed by maybe_constant_value, even in the special cases of those TREE_OVERFLOW_Ps. Note: among various other simplifications, I tried removing the early return via the conditional: if (type_unknown_p (t) || BRACE_ENCLOSED_INITIALIZER_P (t)) but it's actually used by eg, g++.dg/cpp0x/constexpr-initlist5.C. I'm attaching what passed testing on x86_64-linux. Thanks! Paolo. ////////////////////////////// [-- Attachment #2: patchlet4 --] [-- Type: text/plain, Size: 17488 bytes --] Index: cp/call.c =================================================================== --- cp/call.c (revision 217547) +++ cp/call.c (working copy) @@ -572,7 +572,7 @@ null_ptr_cst_p (tree t) { /* Core issue 903 says only literal 0 is a null pointer constant. */ if (cxx_dialect < cxx11) - t = maybe_constant_value (fold_non_dependent_expr_sfinae (t, tf_none)); + t = fold_non_dependent_expr (t); STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; @@ -7437,8 +7437,8 @@ build_over_call (struct z_candidate *cand, int fla return error_mark_node; if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0 - /* Don't mess with virtual lookup in fold_non_dependent_expr; virtual - functions can't be constexpr. */ + /* Don't mess with virtual lookup in instantiate_non_dependent_expr; + virtual functions can't be constexpr. */ && !in_template_function ()) { tree t; @@ -9361,7 +9361,7 @@ perform_implicit_conversion_flags (tree type, tree type of non-dependent expressions, so we do not have to perform the actual conversion. But for initializers, we need to be able to perform it at instantiation - (or fold_non_dependent_expr) time. */ + (or instantiate_non_dependent_expr) time. */ expr = build1 (IMPLICIT_CONV_EXPR, type, expr); if (!(flags & LOOKUP_ONLYCONVERTING)) IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true; Index: cp/class.c =================================================================== --- cp/class.c (revision 217547) +++ cp/class.c (working copy) @@ -359,9 +359,9 @@ build_base_path (enum tree_code code, /* Don't bother with the calculations inside sizeof; they'll ICE if the source type is incomplete and the pointer value doesn't matter. In a - template (even in fold_non_dependent_expr), we don't have vtables set - up properly yet, and the value doesn't matter there either; we're just - interested in the result of overload resolution. */ + template (even in instantiate_non_dependent_expr), we don't have vtables + set up properly yet, and the value doesn't matter there either; we're + just interested in the result of overload resolution. */ if (cp_unevaluated_operand != 0 || in_template_function ()) { @@ -6933,7 +6933,8 @@ resolves_to_fixed_type_p (tree instance, int* nonn tree fixed; /* processing_template_decl can be false in a template if we're in - fold_non_dependent_expr, but we still want to suppress this check. */ + instantiate_non_dependent_expr, but we still want to suppress + this check. */ if (in_template_function ()) { /* In a template we only care about the type of the result. */ Index: cp/constexpr.c =================================================================== --- cp/constexpr.c (revision 217547) +++ cp/constexpr.c (working copy) @@ -2908,6 +2908,7 @@ maybe_constant_value (tree t, tree decl) /* cp_tree_equal looks through NOPs, so allow them. */ gcc_assert (r == t || CONVERT_EXPR_P (t) + || TREE_CODE (t) == VIEW_CONVERT_EXPR || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) || !cp_tree_equal (r, t)); #endif @@ -2914,6 +2915,71 @@ maybe_constant_value (tree t, tree decl) return r; } +/* Like maybe_constant_value but first fully constant fold the argument. */ + +tree +fold_non_dependent_expr (tree t) +{ + if (t == NULL_TREE) + return NULL_TREE; + + /* If we're in a template, but T isn't value dependent, simplify + it. We're supposed to treat: + + template <typename T> void f(T[1 + 1]); + template <typename T> void f(T[2]); + + as two declarations of the same function, for example. */ + if (processing_template_decl) + { + if (!instantiation_dependent_expression_p (t) + && potential_constant_expression (t)) + { + HOST_WIDE_INT saved_processing_template_decl; + + saved_processing_template_decl = processing_template_decl; + processing_template_decl = 0; + t = tsubst_copy_and_build (t, + /*args=*/NULL_TREE, + tf_none, + /*in_decl=*/NULL_TREE, + /*function_p=*/false, + /*integral_constant_expression_p=*/true); + processing_template_decl = saved_processing_template_decl; + + if (type_unknown_p (t) + || BRACE_ENCLOSED_INITIALIZER_P (t)) + { + if (TREE_OVERFLOW_P (t)) + { + t = build_nop (TREE_TYPE (t), t); + TREE_CONSTANT (t) = false; + } + return t; + } + + tree r = cxx_eval_outermost_constant_expr (t, true, NULL_TREE); +#ifdef ENABLE_CHECKING + /* cp_tree_equal looks through NOPs, so allow them. */ + gcc_assert (r == t + || CONVERT_EXPR_P (t) + || TREE_CODE (t) == VIEW_CONVERT_EXPR + || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) + || !cp_tree_equal (r, t)); +#endif + return r; + } + else if (TREE_OVERFLOW_P (t)) + { + t = build_nop (TREE_TYPE (t), t); + TREE_CONSTANT (t) = false; + } + return t; + } + + return maybe_constant_value (t); +} + /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather than wrapped in a TARGET_EXPR. */ @@ -3386,7 +3452,7 @@ potential_constant_expression_1 (tree t, bool want if (!potential_constant_expression_1 (denom, rval, flags)) return false; /* We can't call cxx_eval_outermost_constant_expr on an expression - that hasn't been through fold_non_dependent_expr yet. */ + that hasn't been through instantiate_non_dependent_expr yet. */ if (!processing_template_decl) denom = cxx_eval_outermost_constant_expr (denom, true); if (integer_zerop (denom)) Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 217547) +++ cp/cp-tree.h (working copy) @@ -5690,8 +5690,8 @@ extern tree template_for_substitution (tree); extern tree build_non_dependent_expr (tree); extern void make_args_non_dependent (vec<tree, va_gc> *); extern bool reregister_specialization (tree, tree, tree); -extern tree fold_non_dependent_expr (tree); -extern tree fold_non_dependent_expr_sfinae (tree, tsubst_flags_t); +extern tree instantiate_non_dependent_expr (tree); +extern tree instantiate_non_dependent_expr_sfinae (tree, tsubst_flags_t); extern bool alias_type_or_template_p (tree); extern bool alias_template_specialization_p (const_tree); extern bool dependent_alias_template_spec_p (const_tree); @@ -6331,6 +6331,7 @@ extern bool require_potential_rvalue_constant_expr extern tree cxx_constant_value (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 bool is_sub_constant_expr (tree); extern bool reduced_constant_expression_p (tree); extern bool is_instantiation_of_constexpr (tree); Index: cp/decl.c =================================================================== --- cp/decl.c (revision 217547) +++ cp/decl.c (working copy) @@ -8356,7 +8356,7 @@ compute_array_index_type (tree name, tree size, ts NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */; else { - size = fold_non_dependent_expr_sfinae (size, complain); + size = instantiate_non_dependent_expr_sfinae (size, complain); if (CLASS_TYPE_P (type) && CLASSTYPE_LITERAL_P (type)) @@ -12999,6 +12999,11 @@ build_enumerator (tree name, tree value, tree enum tree context; tree type; + /* integral_constant_value will pull out this expression, so make sure + it's folded as appropriate. */ + if (processing_template_decl) + value = fold_non_dependent_expr (value); + /* If the VALUE was erroneous, pretend it wasn't there; that will result in the enum being assigned the next value in sequence. */ if (value == error_mark_node) Index: cp/decl2.c =================================================================== --- cp/decl2.c (revision 217547) +++ cp/decl2.c (working copy) @@ -4951,7 +4951,7 @@ mark_used (tree decl, tsubst_flags_t complain) if (processing_template_decl) return true; - /* Check this too in case we're within fold_non_dependent_expr. */ + /* Check this too in case we're within instantiate_non_dependent_expr. */ if (DECL_TEMPLATE_INFO (decl) && uses_template_parms (DECL_TI_ARGS (decl))) return true; Index: cp/parser.c =================================================================== --- cp/parser.c (revision 217547) +++ cp/parser.c (working copy) @@ -6886,7 +6886,7 @@ cp_parser_parenthesized_expression_list (cp_parser } if (fold_expr_p) - expr = fold_non_dependent_expr (expr); + expr = instantiate_non_dependent_expr (expr); /* If we have an ellipsis, then this is an expression expansion. */ @@ -15996,10 +15996,6 @@ cp_parser_enumerator_definition (cp_parser* parser if (check_for_bare_parameter_packs (value)) value = error_mark_node; - /* integral_constant_value will pull out this expression, so make sure - it's folded as appropriate. */ - value = fold_non_dependent_expr (value); - /* Create the enumerator. */ build_enumerator (identifier, value, type, loc); } Index: cp/pt.c =================================================================== --- cp/pt.c (revision 217547) +++ cp/pt.c (working copy) @@ -5216,7 +5216,7 @@ redeclare_class_template (tree type, tree parms) (possibly simplified) expression. */ tree -fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) +instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) { if (expr == NULL_TREE) return NULL_TREE; @@ -5248,9 +5248,9 @@ tree } tree -fold_non_dependent_expr (tree expr) +instantiate_non_dependent_expr (tree expr) { - return fold_non_dependent_expr_sfinae (expr, tf_error); + return instantiate_non_dependent_expr_sfinae (expr, tf_error); } /* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias @@ -5740,7 +5740,7 @@ convert_nontype_argument (tree type, tree expr, ts && has_value_dependent_address (expr)) /* If we want the address and it's value-dependent, don't fold. */; else if (!type_unknown_p (expr)) - expr = fold_non_dependent_expr_sfinae (expr, complain); + expr = instantiate_non_dependent_expr_sfinae (expr, complain); if (error_operand_p (expr)) return error_mark_node; expr_type = TREE_TYPE (expr); @@ -8314,7 +8314,7 @@ uses_template_parms (tree t) /* Returns true iff current_function_decl is an incompletely instantiated template. Useful instead of processing_template_decl because the latter - is set to 0 during fold_non_dependent_expr. */ + is set to 0 during instantiate_non_dependent_expr. */ bool in_template_function (void) @@ -15138,8 +15138,7 @@ tsubst_copy_and_build (tree t, case COND_EXPR: { tree cond = RECUR (TREE_OPERAND (t, 0)); - tree folded_cond = (maybe_constant_value - (fold_non_dependent_expr_sfinae (cond, tf_none))); + tree folded_cond = fold_non_dependent_expr (cond); tree exp1, exp2; if (TREE_CODE (folded_cond) == INTEGER_CST) @@ -21110,7 +21109,7 @@ value_dependent_expression_p (tree expression) case STMT_EXPR: /* Treat a GNU statement expression as dependent to avoid crashing - under fold_non_dependent_expr; it can't be constant. */ + under instantiate_non_dependent_expr; it can't be constant. */ return true; default: @@ -21864,7 +21863,7 @@ build_non_dependent_expr (tree expr) /* Try to get a constant value for all non-dependent expressions in order to expose bugs in *_dependent_expression_p and constexpr. */ if (cxx_dialect >= cxx11) - maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none)); + fold_non_dependent_expr (expr); #endif /* Preserve OVERLOADs; the functions must be available to resolve Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 217547) +++ cp/semantics.c (working copy) @@ -511,8 +511,7 @@ begin_maybe_infinite_loop (tree cond) bool maybe_infinite = true; if (cond) { - cond = fold_non_dependent_expr_sfinae (cond, tf_none); - cond = maybe_constant_value (cond); + cond = fold_non_dependent_expr (cond); maybe_infinite = integer_nonzerop (cond); } vec_safe_push (cp_function_chain->infinite_loops, @@ -543,7 +542,6 @@ end_maybe_infinite_loop (tree cond) if (current != NULL_TREE) { cond = fold_non_dependent_expr (cond); - cond = maybe_constant_value (cond); if (integer_nonzerop (cond)) current_function_infinite_loop = 1; } @@ -7043,7 +7041,7 @@ finish_static_assert (tree condition, tree message } /* Fold the expression and convert it to a boolean value. */ - condition = fold_non_dependent_expr (condition); + condition = instantiate_non_dependent_expr (condition); condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); Index: cp/tree.c =================================================================== --- cp/tree.c (revision 217547) +++ cp/tree.c (working copy) @@ -4143,7 +4143,7 @@ fold_if_not_in_template (tree expr) /* In the body of a template, there is never any need to call "fold". We will call fold later when actually instantiating the template. Integral constant expressions in templates will be - evaluated via fold_non_dependent_expr, as necessary. */ + evaluated via instantiate_non_dependent_expr, as necessary. */ if (processing_template_decl) return expr; Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 217547) +++ cp/typeck.c (working copy) @@ -1787,7 +1787,7 @@ cxx_alignas_expr (tree e) /* Leave value-dependent expression alone for now. */ return e; - e = fold_non_dependent_expr (e); + e = instantiate_non_dependent_expr (e); e = mark_rvalue_use (e); /* [dcl.align]/2 says: @@ -4135,8 +4135,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_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = fold_non_dependent_expr (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); @@ -4175,8 +4174,7 @@ cp_build_binary_op (location_t location, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: { - tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); - cop1 = maybe_constant_value (cop1); + tree cop1 = fold_non_dependent_expr (op1); doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); } @@ -4270,8 +4268,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = fold_non_dependent_expr (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4320,8 +4317,7 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); - const_op1 = maybe_constant_value (const_op1); + tree const_op1 = fold_non_dependent_expr (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4993,10 +4989,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 = maybe_constant_value (fold_non_dependent_expr_sfinae (op0, - tf_none)); - op1 = maybe_constant_value (fold_non_dependent_expr_sfinae (op1, - tf_none)); + op0 = fold_non_dependent_expr (op0); + op1 = fold_non_dependent_expr (op1); if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))) { Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 217547) +++ cp/typeck2.c (working copy) @@ -797,7 +797,7 @@ store_init_value (tree decl, tree init, vec<tree, if (decl_maybe_constant_var_p (decl) || TREE_STATIC (decl)) { bool const_init; - value = fold_non_dependent_expr (value); + value = instantiate_non_dependent_expr (value); if (DECL_DECLARED_CONSTEXPR_P (decl) || DECL_IN_AGGR_P (decl)) { @@ -872,7 +872,7 @@ check_narrowing (tree type, tree init, tsubst_flag return ok; } - init = maybe_constant_value (fold_non_dependent_expr_sfinae (init, tf_none)); + init = fold_non_dependent_expr (init); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (ftype) == REAL_TYPE) @@ -1176,7 +1176,7 @@ massage_init_elt (tree type, tree init, tsubst_fla 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_sfinae (init, complain); + tree t = fold_non_dependent_expr (init); t = maybe_constant_init (t); if (TREE_CONSTANT (t)) init = t; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] Add maybe_constant_folded_value 2014-11-14 14:06 ` Paolo Carlini @ 2014-11-14 14:09 ` Jason Merrill 0 siblings, 0 replies; 10+ messages in thread From: Jason Merrill @ 2014-11-14 14:09 UTC (permalink / raw) To: Paolo Carlini, gcc-patches, Tietz, Kai On 11/14/2014 08:46 AM, Paolo Carlini wrote: > +/* Like maybe_constant_value but first fully constant fold the argument. */ "but first fully instantiate the argument." OK with that change, thanks. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-11-14 13:52 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-11-13 10:54 [C++ Patch] Add maybe_constant_folded_value Paolo Carlini 2014-11-13 16:41 ` Jason Merrill 2014-11-13 16:43 ` Kai Tietz 2014-11-13 16:43 ` Jason Merrill 2014-11-13 17:50 ` Paolo Carlini 2014-11-13 18:40 ` Jason Merrill 2014-11-13 21:45 ` Paolo Carlini 2014-11-14 4:25 ` Jason Merrill 2014-11-14 14:06 ` Paolo Carlini 2014-11-14 14:09 ` Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).