* [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 ` Jason Merrill
2014-11-13 16:43 ` Kai Tietz
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 ` Jason Merrill
@ 2014-11-13 16:43 ` Kai Tietz
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 ` Jason Merrill
2014-11-13 17:50 ` Paolo Carlini
2014-11-13 16:43 ` Kai Tietz
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 ` 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
2014-11-13 16:43 ` Kai Tietz
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).