aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constexpr.c
diff options
context:
space:
mode:
authorJason Merrill <jason@gcc.gnu.org>2015-11-13 19:08:05 -0500
committerJason Merrill <jason@gcc.gnu.org>2015-11-13 19:08:05 -0500
commitcda0a029f45d20f4535dcacf6c3194352c31e736 (patch)
treee5f2d64459601fae812cfe90245af2831eebedb1 /gcc/cp/constexpr.c
parent8fe17e23b052741c8cbec99c7173c3c07f8e8c64 (diff)
downloadgcc-cda0a029f45d20f4535dcacf6c3194352c31e736.zip
gcc-cda0a029f45d20f4535dcacf6c3194352c31e736.tar.gz
gcc-cda0a029f45d20f4535dcacf6c3194352c31e736.tar.bz2
Merge C++ delayed folding branch.
* call.c (build_conditional_expr_1, convert_like_real) (convert_arg_to_ellipsis, convert_for_arg_passing): Don't fold. (build_new_op_1, build_over_call, build_cxx_call): Fold for warnings. * class.c (build_base_path, determine_primary_bases) (update_vtable_entry_for_fn, check_bitfield_decl) (layout_nonempty_base_or_field, layout_empty_base) (propagate_binfo_offsets, include_empty_classes) (layout_class_type, build_vbase_offset_vtbl_entries): Use fold_convert. * constexpr.c (cxx_eval_builtin_function_call): Fold away the NOP_EXPR. (cxx_eval_call_expression): Handle MEM_REF. (cxx_eval_pointer_plus_expression): Fold the second operand. (cxx_eval_constant_expression): Handle MEM_REF, UNARY_PLUS_EXPR. (fold_simple_1, fold_simple): New. (maybe_constant_value_1): Factor out from maybe_constant_value. (cv_cache, maybe_constant_value): Cache results. (maybe_constant_init): Handle null input. (potential_constant_expression_1): Handle RESULT_DECL, EMPTY_CLASS_EXPR. * cp-array-notation.c (build_array_notation_ref): Fold operands. * cp-gimplify.c (cp_fold_r, cp_fold): New. (cp_genericize_r): Use fold_convert. Don't fold SIZEOF_EXPR. (cp_genericize): Fold everything. (contains_label_1, contains_label_p): New. (cp_fold, cp_fully_fold): New. * cp-tree.h (class cache_map): New. * cvt.c (cp_convert_to_pointer, ocp_convert): Use convert_to_*_nofold. (cp_convert_and_check): Use cp_fully_fold. (convert, convert_force): Don't fold. * decl.c (fold_sizeof_expr): Change from fold_sizeof_expr_r. (compute_array_index_type): Use cp_fully_fold. (build_enumerator): Use fold_convert. * decl2.c (get_guard_cond, set_guard): Use fold_convert. * init.c (build_zero_init_1): Fold zero-initializers. (build_new_1): Fold nelts calculations. (build_vec_delete_1): Fold conversions. (build_vec_init): Fold maxindex. * parser.c (cp_parser_binary_expression): Fold LHS of || and &&. (cp_parser_question_colon_clause): Fold LHS. * pt.c (convert_nontype_argument): Fold nullptr conversion. * semantics.c (finish_unary_op_expr): Fold for warnings. (handle_omp_array_sections_1): Fold length and low bound. (handle_omp_for_class_iterator): Fold various things. * tree.c (builtin_valid_in_constant_expr_p): Add BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE. (convert_bitfield_to_declared_type): Don't fold. (handle_init_priority_attribute): Fold. (fold_if_not_in_template): Remove. * typeck.c (decay_conversion, build_class_member_access_expr) (build_simple_component_ref, cp_build_array_ref, build_vec_cmp) (cp_pointer_int_sum, pointer_diff): Don't fold. (cp_build_binary_op): Fold for warnings and PMF ops. (cp_build_unary_op): Fold negation of a constant, nothing else. (expand_ptrmemfunc_cst): Fold operations. * typeck2.c (split_nonconstant_init): Fold initializer. (store_init_value): Likewise. (check_narrowing): Try folding. * config-lang.in (gtfiles): Add cp-gimplify.c. From-SVN: r230365
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r--gcc/cp/constexpr.c150
1 files changed, 135 insertions, 15 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 159c4b3..aabb980 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1035,6 +1035,8 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
force_folding_builtin_constant_p = true;
new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
CALL_EXPR_FN (t), nargs, args);
+ /* Fold away the NOP_EXPR from fold_builtin_n. */
+ new_call = fold (new_call);
force_folding_builtin_constant_p = save_ffbcp;
VERIFY_CONSTANT (new_call);
return new_call;
@@ -1275,6 +1277,16 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
ctx->values->put (new_ctx.object, ctor);
ctx = &new_ctx;
}
+ else if (DECL_BY_REFERENCE (DECL_RESULT (fun))
+ && TREE_CODE (t) != AGGR_INIT_EXPR)
+ {
+ /* convert_to_void stripped our AGGR_INIT_EXPR, in which case we don't
+ care about a constant value. ??? we could still optimize away the
+ call. */
+ gcc_assert (ctx->quiet && !ctx->object);
+ *non_constant_p = true;
+ return t;
+ }
bool non_constant_args = false;
cxx_bind_parameters_in_call (ctx, t, &new_call,
@@ -2540,6 +2552,17 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
tree orig_op0 = TREE_OPERAND (t, 0);
bool empty_base = false;
+ /* We can handle a MEM_REF like an INDIRECT_REF, if MEM_REF's second
+ operand is an integer-zero. Otherwise reject the MEM_REF for now. */
+
+ if (TREE_CODE (t) == MEM_REF
+ && (!TREE_OPERAND (t, 1) || !integer_zerop (TREE_OPERAND (t, 1))))
+ {
+ gcc_assert (ctx->quiet);
+ *non_constant_p = true;
+ return t;
+ }
+
/* First try to simplify it directly. */
tree r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), orig_op0,
&empty_base);
@@ -3073,6 +3096,8 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
if (TREE_CODE (op00) != ADDR_EXPR)
return NULL_TREE;
+ op01 = cxx_eval_constant_expression (ctx, op01, lval,
+ non_constant_p, overflow_p);
op00 = TREE_OPERAND (op00, 0);
/* &A[i] p+ j => &A[i + j] */
@@ -3333,6 +3358,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
/* These differ from cxx_eval_unary_expression in that this doesn't
check for a constant operand or result; an address can be
constant without its operand being, and vice versa. */
+ case MEM_REF:
case INDIRECT_REF:
r = cxx_eval_indirect_ref (ctx, t, lval,
non_constant_p, overflow_p);
@@ -3370,17 +3396,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case SIZEOF_EXPR:
- if (SIZEOF_EXPR_TYPE_P (t))
- r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
- SIZEOF_EXPR, false);
- else if (TYPE_P (TREE_OPERAND (t, 0)))
- r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
- false);
- else
- r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
- false);
- if (r == error_mark_node)
- r = size_one_node;
+ r = fold_sizeof_expr (t);
VERIFY_CONSTANT (r);
break;
@@ -3538,8 +3554,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case CONVERT_EXPR:
case VIEW_CONVERT_EXPR:
case NOP_EXPR:
+ case UNARY_PLUS_EXPR:
{
+ enum tree_code tcode = TREE_CODE (t);
tree oldop = TREE_OPERAND (t, 0);
+
tree op = cxx_eval_constant_expression (ctx, oldop,
lval,
non_constant_p, overflow_p);
@@ -3559,11 +3578,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
return t;
}
- if (op == oldop)
+ if (op == oldop && tcode != UNARY_PLUS_EXPR)
/* We didn't fold at the top so we could check for ptr-int
conversion. */
return fold (t);
- r = fold_build1 (TREE_CODE (t), type, op);
+ if (tcode == UNARY_PLUS_EXPR)
+ r = fold_convert (TREE_TYPE (t), op);
+ else
+ r = fold_build1 (tcode, type, op);
/* Conversion of an out-of-range value has implementation-defined
behavior; the language considers it different from arithmetic
overflow, which is undefined. */
@@ -3831,12 +3853,86 @@ cxx_constant_value (tree t, tree decl)
return cxx_eval_outermost_constant_expr (t, false, true, decl);
}
+/* Helper routine for fold_simple function. Either return simplified
+ expression T, otherwise NULL_TREE.
+ In contrast to cp_fully_fold, and to maybe_constant_value, we try to fold
+ even if we are within template-declaration. So be careful on call, as in
+ such case types can be undefined. */
+
+static tree
+fold_simple_1 (tree t)
+{
+ tree op1;
+ enum tree_code code = TREE_CODE (t);
+
+ switch (code)
+ {
+ case INTEGER_CST:
+ case REAL_CST:
+ case VECTOR_CST:
+ case FIXED_CST:
+ case COMPLEX_CST:
+ return t;
+
+ case SIZEOF_EXPR:
+ return fold_sizeof_expr (t);
+
+ case ABS_EXPR:
+ case CONJ_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case NOP_EXPR:
+ case VIEW_CONVERT_EXPR:
+ case CONVERT_EXPR:
+ case FLOAT_EXPR:
+ case FIX_TRUNC_EXPR:
+ case FIXED_CONVERT_EXPR:
+ case ADDR_SPACE_CONVERT_EXPR:
+
+ op1 = TREE_OPERAND (t, 0);
+
+ t = const_unop (code, TREE_TYPE (t), op1);
+ if (!t)
+ return NULL_TREE;
+
+ if (CONVERT_EXPR_CODE_P (code)
+ && TREE_OVERFLOW_P (t) && !TREE_OVERFLOW_P (op1))
+ TREE_OVERFLOW (t) = false;
+ return t;
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* If T is a simple constant expression, returns its simplified value.
+ Otherwise returns T. In contrast to maybe_constant_value do we
+ simplify only few operations on constant-expressions, and we don't
+ try to simplify constexpressions. */
+
+tree
+fold_simple (tree t)
+{
+ tree r = NULL_TREE;
+ if (processing_template_decl)
+ return t;
+
+ r = fold_simple_1 (t);
+ if (!r)
+ r = t;
+
+ return r;
+}
+
/* If T is a constant expression, returns its reduced value.
Otherwise, if T does not have TREE_CONSTANT set, returns T.
Otherwise, returns a version of T without TREE_CONSTANT. */
-tree
-maybe_constant_value (tree t, tree decl)
+static tree
+maybe_constant_value_1 (tree t, tree decl)
{
tree r;
@@ -3862,6 +3958,24 @@ maybe_constant_value (tree t, tree decl)
return r;
}
+static GTY((cache, deletable)) cache_map cv_cache;
+
+/* If T is a constant expression, returns its reduced value.
+ Otherwise, if T does not have TREE_CONSTANT set, returns T.
+ Otherwise, returns a version of T without TREE_CONSTANT. */
+
+tree
+maybe_constant_value (tree t, tree decl)
+{
+ tree ret = cv_cache.get (t);
+ if (!ret)
+ {
+ ret = maybe_constant_value_1 (t, decl);
+ cv_cache.put (t, ret);
+ }
+ return ret;
+}
+
/* Like maybe_constant_value but first fully instantiate the argument.
Note: this is equivalent to instantiate_non_dependent_expr_sfinae
@@ -3927,6 +4041,8 @@ fold_non_dependent_expr (tree t)
tree
maybe_constant_init (tree t, tree decl)
{
+ if (!t)
+ return t;
if (TREE_CODE (t) == EXPR_STMT)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CONVERT_EXPR
@@ -4037,6 +4153,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
/* We can see a FIELD_DECL in a pointer-to-member expression. */
case FIELD_DECL:
case PARM_DECL:
+ case RESULT_DECL:
case USING_DECL:
case USING_STMT:
case PLACEHOLDER_EXPR:
@@ -4625,6 +4742,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
/* We can see these in statement-expressions. */
return true;
+ case EMPTY_CLASS_EXPR:
+ return false;
+
default:
if (objc_is_property_ref (t))
return false;