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
This commit is contained in:
parent
8fe17e23b0
commit
cda0a029f4
@ -1,3 +1,65 @@
|
||||
2015-11-13 Kai Tietz <ktietz70@googlemail.com>
|
||||
Marek Polacek <polacek@redhat.com>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2015-11-13 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* error.c (pedwarn_cxx98): Pass line_table to rich_location ctor.
|
||||
|
@ -4748,7 +4748,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
|
||||
tree cmp_type = build_same_sized_truth_vector_type (arg1_type);
|
||||
arg1 = build2 (NE_EXPR, cmp_type, arg1, build_zero_cst (arg1_type));
|
||||
}
|
||||
return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
|
||||
return build3_loc (loc, VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
/* [expr.cond]
|
||||
@ -5152,9 +5152,6 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
|
||||
|
||||
valid_operands:
|
||||
result = build3_loc (loc, COND_EXPR, result_type, arg1, arg2, arg3);
|
||||
if (!cp_unevaluated_operand)
|
||||
/* Avoid folding within decltype (c++/42013) and noexcept. */
|
||||
result = fold_if_not_in_template (result);
|
||||
|
||||
/* We can't use result_type below, as fold might have returned a
|
||||
throw_expr. */
|
||||
@ -5690,8 +5687,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
|
||||
decaying an enumerator to its value. */
|
||||
if (complain & tf_warning)
|
||||
warn_logical_operator (loc, code, boolean_type_node,
|
||||
code_orig_arg1, arg1,
|
||||
code_orig_arg2, arg2);
|
||||
code_orig_arg1, fold (arg1),
|
||||
code_orig_arg2, fold (arg2));
|
||||
|
||||
arg2 = convert_like (conv, arg2, complain);
|
||||
}
|
||||
@ -5729,7 +5726,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
|
||||
case TRUTH_OR_EXPR:
|
||||
if (complain & tf_warning)
|
||||
warn_logical_operator (loc, code, boolean_type_node,
|
||||
code_orig_arg1, arg1, code_orig_arg2, arg2);
|
||||
code_orig_arg1, fold (arg1),
|
||||
code_orig_arg2, fold (arg2));
|
||||
/* Fall through. */
|
||||
case GT_EXPR:
|
||||
case LT_EXPR:
|
||||
@ -5740,9 +5738,10 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
|
||||
if ((complain & tf_warning)
|
||||
&& ((code_orig_arg1 == BOOLEAN_TYPE)
|
||||
^ (code_orig_arg2 == BOOLEAN_TYPE)))
|
||||
maybe_warn_bool_compare (loc, code, arg1, arg2);
|
||||
maybe_warn_bool_compare (loc, code, fold (arg1),
|
||||
fold (arg2));
|
||||
if (complain & tf_warning && warn_tautological_compare)
|
||||
warn_tautological_cmp (loc, code, arg1, arg2);
|
||||
warn_tautological_cmp (loc, code, fold (arg1), fold (arg2));
|
||||
/* Fall through. */
|
||||
case PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
@ -6496,7 +6495,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
||||
imag = perform_implicit_conversion (TREE_TYPE (totype),
|
||||
imag, complain);
|
||||
expr = build2 (COMPLEX_EXPR, totype, real, imag);
|
||||
return fold_if_not_in_template (expr);
|
||||
return expr;
|
||||
}
|
||||
expr = reshape_init (totype, expr, complain);
|
||||
expr = get_target_expr_sfinae (digest_init (totype, expr, complain),
|
||||
@ -6737,7 +6736,7 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
|
||||
"implicit conversion from %qT to %qT when passing "
|
||||
"argument to function",
|
||||
arg_type, double_type_node);
|
||||
arg = convert_to_real (double_type_node, arg);
|
||||
arg = convert_to_real_nofold (double_type_node, arg);
|
||||
}
|
||||
else if (NULLPTR_TYPE_P (arg_type))
|
||||
arg = null_pointer_node;
|
||||
@ -6982,7 +6981,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
|
||||
bitfield_type = is_bitfield_expr_with_lowered_type (val);
|
||||
if (bitfield_type
|
||||
&& TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type))
|
||||
val = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type), val);
|
||||
val = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type), val);
|
||||
|
||||
if (val == error_mark_node)
|
||||
;
|
||||
@ -7502,7 +7501,19 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
||||
gcc_assert (j <= nargs);
|
||||
nargs = j;
|
||||
|
||||
check_function_arguments (TREE_TYPE (fn), nargs, argarray);
|
||||
/* Avoid to do argument-transformation, if warnings for format, and for
|
||||
nonnull are disabled. Just in case that at least one of them is active
|
||||
the check_function_arguments function might warn about something. */
|
||||
|
||||
if (warn_nonnull || warn_format || warn_suggest_attribute_format)
|
||||
{
|
||||
tree *fargs = (!nargs ? argarray
|
||||
: (tree *) alloca (nargs * sizeof (tree)));
|
||||
for (j = 0; j < nargs; j++)
|
||||
fargs[j] = maybe_constant_value (argarray[j]);
|
||||
|
||||
check_function_arguments (TREE_TYPE (fn), nargs, fargs);
|
||||
}
|
||||
|
||||
/* Avoid actually calling copy constructors and copy assignment operators,
|
||||
if possible. */
|
||||
@ -7693,7 +7704,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
|
||||
tsubst_flags_t complain)
|
||||
{
|
||||
tree fndecl;
|
||||
int optimize_sav;
|
||||
|
||||
/* Remember roughly where this call is. */
|
||||
location_t loc = EXPR_LOC_OR_LOC (fn, input_location);
|
||||
@ -7705,9 +7715,18 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
|
||||
/* Check that arguments to builtin functions match the expectations. */
|
||||
if (fndecl
|
||||
&& DECL_BUILT_IN (fndecl)
|
||||
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
|
||||
&& !check_builtin_function_arguments (fndecl, nargs, argarray))
|
||||
return error_mark_node;
|
||||
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We need to take care that values to BUILT_IN_NORMAL
|
||||
are reduced. */
|
||||
for (i = 0; i < nargs; i++)
|
||||
argarray[i] = maybe_constant_value (argarray[i]);
|
||||
|
||||
if (!check_builtin_function_arguments (fndecl, nargs, argarray))
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* If it is a built-in array notation function, then the return type of
|
||||
the function is the element type of the array passed in as array
|
||||
@ -7741,17 +7760,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
|
||||
}
|
||||
}
|
||||
|
||||
/* Some built-in function calls will be evaluated at compile-time in
|
||||
fold (). Set optimize to 1 when folding __builtin_constant_p inside
|
||||
a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
|
||||
optimize_sav = optimize;
|
||||
if (!optimize && fndecl && DECL_IS_BUILTIN_CONSTANT_P (fndecl)
|
||||
&& current_function_decl
|
||||
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
|
||||
optimize = 1;
|
||||
fn = fold_if_not_in_template (fn);
|
||||
optimize = optimize_sav;
|
||||
|
||||
if (VOID_TYPE_P (TREE_TYPE (fn)))
|
||||
return fn;
|
||||
|
||||
|
@ -421,7 +421,7 @@ build_base_path (enum tree_code code,
|
||||
|
||||
t = TREE_TYPE (TYPE_VFIELD (current_class_type));
|
||||
t = build_pointer_type (t);
|
||||
v_offset = convert (t, current_vtt_parm);
|
||||
v_offset = fold_convert (t, current_vtt_parm);
|
||||
v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
|
||||
}
|
||||
else
|
||||
@ -554,8 +554,6 @@ build_simple_base_path (tree expr, tree binfo)
|
||||
expr = build3 (COMPONENT_REF,
|
||||
cp_build_qualified_type (type, type_quals),
|
||||
expr, field, NULL_TREE);
|
||||
expr = fold_if_not_in_template (expr);
|
||||
|
||||
/* Mark the expression const or volatile, as appropriate.
|
||||
Even though we've dealt with the type above, we still have
|
||||
to mark the expression itself. */
|
||||
@ -1847,9 +1845,9 @@ determine_primary_bases (tree t)
|
||||
another hierarchy. As we're about to use it as a
|
||||
primary base, make sure the offsets match. */
|
||||
delta = size_diffop_loc (input_location,
|
||||
convert (ssizetype,
|
||||
fold_convert (ssizetype,
|
||||
BINFO_OFFSET (base_binfo)),
|
||||
convert (ssizetype,
|
||||
fold_convert (ssizetype,
|
||||
BINFO_OFFSET (this_primary)));
|
||||
|
||||
propagate_binfo_offsets (this_primary, delta);
|
||||
@ -1911,7 +1909,7 @@ determine_primary_bases (tree t)
|
||||
another hierarchy. As we're about to use it as a primary
|
||||
base, make sure the offsets match. */
|
||||
delta = size_diffop_loc (input_location, ssize_int (0),
|
||||
convert (ssizetype, BINFO_OFFSET (primary)));
|
||||
fold_convert (ssizetype, BINFO_OFFSET (primary)));
|
||||
|
||||
propagate_binfo_offsets (primary, delta);
|
||||
}
|
||||
@ -2635,7 +2633,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
|
||||
if (virtual_offset
|
||||
|| (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo)))
|
||||
{
|
||||
tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
|
||||
tree offset = fold_convert (ssizetype, BINFO_OFFSET (thunk_binfo));
|
||||
|
||||
if (virtual_offset)
|
||||
{
|
||||
@ -2643,7 +2641,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
|
||||
offset to be from there. */
|
||||
offset =
|
||||
size_diffop (offset,
|
||||
convert (ssizetype,
|
||||
fold_convert (ssizetype,
|
||||
BINFO_OFFSET (virtual_offset)));
|
||||
}
|
||||
if (fixed_offset)
|
||||
@ -2732,8 +2730,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
|
||||
/* The `this' pointer needs to be adjusted from the declaration to
|
||||
the nearest virtual base. */
|
||||
delta = size_diffop_loc (input_location,
|
||||
convert (ssizetype, BINFO_OFFSET (virtual_base)),
|
||||
convert (ssizetype, BINFO_OFFSET (first_defn)));
|
||||
fold_convert (ssizetype, BINFO_OFFSET (virtual_base)),
|
||||
fold_convert (ssizetype, BINFO_OFFSET (first_defn)));
|
||||
else if (lost)
|
||||
/* If the nearest definition is in a lost primary, we don't need an
|
||||
entry in our vtable. Except possibly in a constructor vtable,
|
||||
@ -2745,9 +2743,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
|
||||
BINFO to pointing at the base where the final overrider
|
||||
appears. */
|
||||
delta = size_diffop_loc (input_location,
|
||||
convert (ssizetype,
|
||||
fold_convert (ssizetype,
|
||||
BINFO_OFFSET (TREE_VALUE (overrider))),
|
||||
convert (ssizetype, BINFO_OFFSET (binfo)));
|
||||
fold_convert (ssizetype, BINFO_OFFSET (binfo)));
|
||||
|
||||
modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
|
||||
|
||||
@ -3469,7 +3467,7 @@ check_bitfield_decl (tree field)
|
||||
|
||||
if (w != error_mark_node)
|
||||
{
|
||||
DECL_SIZE (field) = convert (bitsizetype, w);
|
||||
DECL_SIZE (field) = fold_convert (bitsizetype, w);
|
||||
DECL_BIT_FIELD (field) = 1;
|
||||
return true;
|
||||
}
|
||||
@ -4314,8 +4312,8 @@ layout_nonempty_base_or_field (record_layout_info rli,
|
||||
OFFSET. */
|
||||
propagate_binfo_offsets (binfo,
|
||||
size_diffop_loc (input_location,
|
||||
convert (ssizetype, offset),
|
||||
convert (ssizetype,
|
||||
fold_convert (ssizetype, offset),
|
||||
fold_convert (ssizetype,
|
||||
BINFO_OFFSET (binfo))));
|
||||
}
|
||||
|
||||
@ -4362,7 +4360,7 @@ layout_empty_base (record_layout_info rli, tree binfo,
|
||||
/* That didn't work. Now, we move forward from the next
|
||||
available spot in the class. */
|
||||
atend = true;
|
||||
propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
|
||||
propagate_binfo_offsets (binfo, fold_convert (ssizetype, eoc));
|
||||
while (1)
|
||||
{
|
||||
if (!layout_conflict_p (binfo,
|
||||
@ -5976,9 +5974,9 @@ propagate_binfo_offsets (tree binfo, tree offset)
|
||||
|
||||
/* Update BINFO's offset. */
|
||||
BINFO_OFFSET (binfo)
|
||||
= convert (sizetype,
|
||||
= fold_convert (sizetype,
|
||||
size_binop (PLUS_EXPR,
|
||||
convert (ssizetype, BINFO_OFFSET (binfo)),
|
||||
fold_convert (ssizetype, BINFO_OFFSET (binfo)),
|
||||
offset));
|
||||
|
||||
/* Find the primary base class. */
|
||||
@ -6183,7 +6181,7 @@ include_empty_classes (record_layout_info rli)
|
||||
= size_binop (PLUS_EXPR,
|
||||
rli->bitpos,
|
||||
size_binop (MULT_EXPR,
|
||||
convert (bitsizetype,
|
||||
fold_convert (bitsizetype,
|
||||
size_binop (MINUS_EXPR,
|
||||
eoc, rli_size)),
|
||||
bitsize_int (BITS_PER_UNIT)));
|
||||
@ -6457,7 +6455,7 @@ layout_class_type (tree t, tree *virtuals_p)
|
||||
eoc = end_of_class (t, /*include_virtuals_p=*/0);
|
||||
TYPE_SIZE_UNIT (base_t)
|
||||
= size_binop (MAX_EXPR,
|
||||
convert (sizetype,
|
||||
fold_convert (sizetype,
|
||||
size_binop (CEIL_DIV_EXPR,
|
||||
rli_size_so_far (rli),
|
||||
bitsize_int (BITS_PER_UNIT))),
|
||||
@ -6466,7 +6464,7 @@ layout_class_type (tree t, tree *virtuals_p)
|
||||
= size_binop (MAX_EXPR,
|
||||
rli_size_so_far (rli),
|
||||
size_binop (MULT_EXPR,
|
||||
convert (bitsizetype, eoc),
|
||||
fold_convert (bitsizetype, eoc),
|
||||
bitsize_int (BITS_PER_UNIT)));
|
||||
TYPE_ALIGN (base_t) = rli->record_align;
|
||||
TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
|
||||
@ -9302,7 +9300,7 @@ build_vbase_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
|
||||
/* Figure out where we can find this vbase offset. */
|
||||
delta = size_binop (MULT_EXPR,
|
||||
vid->index,
|
||||
convert (ssizetype,
|
||||
fold_convert (ssizetype,
|
||||
TYPE_SIZE_UNIT (vtable_entry_type)));
|
||||
if (vid->primary_vtbl_p)
|
||||
BINFO_VPTR_FIELD (b) = delta;
|
||||
|
@ -29,4 +29,4 @@ compilers="cc1plus\$(exeext)"
|
||||
|
||||
target_libs="target-libstdc++-v3"
|
||||
|
||||
gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c"
|
||||
gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.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;
|
||||
|
@ -1380,7 +1380,12 @@ build_array_notation_ref (location_t loc, tree array, tree start, tree length,
|
||||
|
||||
if (!stride)
|
||||
stride = build_one_cst (ptrdiff_type_node);
|
||||
|
||||
|
||||
stride = maybe_constant_value (stride);
|
||||
length = maybe_constant_value (length);
|
||||
if (start)
|
||||
start = maybe_constant_value (start);
|
||||
|
||||
/* When dealing with templates, triplet type-checking will be done in pt.c
|
||||
after type substitution. */
|
||||
if (processing_template_decl
|
||||
|
@ -36,7 +36,9 @@ along with GCC; see the file COPYING3. If not see
|
||||
/* Forward declarations. */
|
||||
|
||||
static tree cp_genericize_r (tree *, int *, void *);
|
||||
static tree cp_fold_r (tree *, int *, void *);
|
||||
static void cp_genericize_tree (tree*);
|
||||
static tree cp_fold (tree);
|
||||
|
||||
/* Local declarations. */
|
||||
|
||||
@ -914,6 +916,71 @@ struct cp_genericize_data
|
||||
bool no_sanitize_p;
|
||||
};
|
||||
|
||||
/* Perform any pre-gimplification folding of C++ front end trees to
|
||||
GENERIC.
|
||||
Note: The folding of none-omp cases is something to move into
|
||||
the middle-end. As for now we have most foldings only on GENERIC
|
||||
in fold-const, we need to perform this before transformation to
|
||||
GIMPLE-form. */
|
||||
|
||||
static tree
|
||||
cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data)
|
||||
{
|
||||
tree stmt;
|
||||
enum tree_code code;
|
||||
|
||||
*stmt_p = stmt = cp_fold (*stmt_p);
|
||||
|
||||
code = TREE_CODE (stmt);
|
||||
if (code == OMP_FOR || code == OMP_SIMD || code == OMP_DISTRIBUTE
|
||||
|| code == OMP_TASKLOOP || code == CILK_FOR || code == CILK_SIMD)
|
||||
{
|
||||
tree x;
|
||||
int i, n;
|
||||
|
||||
cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL);
|
||||
cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL);
|
||||
cp_walk_tree (&OMP_FOR_INIT (stmt), cp_fold_r, data, NULL);
|
||||
x = OMP_FOR_COND (stmt);
|
||||
if (x && TREE_CODE_CLASS (TREE_CODE (x)) == tcc_comparison)
|
||||
{
|
||||
cp_walk_tree (&TREE_OPERAND (x, 0), cp_fold_r, data, NULL);
|
||||
cp_walk_tree (&TREE_OPERAND (x, 1), cp_fold_r, data, NULL);
|
||||
}
|
||||
else if (x && TREE_CODE (x) == TREE_VEC)
|
||||
{
|
||||
n = TREE_VEC_LENGTH (x);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
tree o = TREE_VEC_ELT (x, i);
|
||||
if (o && TREE_CODE_CLASS (TREE_CODE (o)) == tcc_comparison)
|
||||
cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
|
||||
}
|
||||
}
|
||||
x = OMP_FOR_INCR (stmt);
|
||||
if (x && TREE_CODE (x) == TREE_VEC)
|
||||
{
|
||||
n = TREE_VEC_LENGTH (x);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
tree o = TREE_VEC_ELT (x, i);
|
||||
if (o && TREE_CODE (o) == MODIFY_EXPR)
|
||||
o = TREE_OPERAND (o, 1);
|
||||
if (o && (TREE_CODE (o) == PLUS_EXPR || TREE_CODE (o) == MINUS_EXPR
|
||||
|| TREE_CODE (o) == POINTER_PLUS_EXPR))
|
||||
{
|
||||
cp_walk_tree (&TREE_OPERAND (o, 0), cp_fold_r, data, NULL);
|
||||
cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_fold_r, data, NULL);
|
||||
*walk_subtrees = 0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Perform any pre-gimplification lowering of C++ front end trees to
|
||||
GENERIC. */
|
||||
|
||||
@ -973,7 +1040,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
|
||||
if (__builtin_expect (wtd->omp_ctx != NULL, 0)
|
||||
&& omp_var_to_track (TREE_OPERAND (stmt, 0)))
|
||||
omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
|
||||
*stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
|
||||
*stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
|
||||
*walk_subtrees = 0;
|
||||
}
|
||||
else if (TREE_CODE (stmt) == RETURN_EXPR
|
||||
@ -1288,22 +1355,6 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
|
||||
|| TREE_CODE (stmt) == OMP_DISTRIBUTE
|
||||
|| TREE_CODE (stmt) == OMP_TASKLOOP)
|
||||
genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
|
||||
else if (TREE_CODE (stmt) == SIZEOF_EXPR)
|
||||
{
|
||||
if (SIZEOF_EXPR_TYPE_P (stmt))
|
||||
*stmt_p
|
||||
= cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)),
|
||||
SIZEOF_EXPR, false);
|
||||
else if (TYPE_P (TREE_OPERAND (stmt, 0)))
|
||||
*stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0),
|
||||
SIZEOF_EXPR, false);
|
||||
else
|
||||
*stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0),
|
||||
SIZEOF_EXPR, false);
|
||||
if (*stmt_p == error_mark_node)
|
||||
*stmt_p = size_one_node;
|
||||
return NULL;
|
||||
}
|
||||
else if ((flag_sanitize
|
||||
& (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
|
||||
&& !wtd->no_sanitize_p)
|
||||
@ -1414,6 +1465,10 @@ cp_genericize (tree fndecl)
|
||||
{
|
||||
tree t;
|
||||
|
||||
/* Fold ALL the trees! FIXME we should be able to remove this, but
|
||||
apparently that still causes optimization regressions. */
|
||||
cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, NULL, NULL);
|
||||
|
||||
/* Fix up the types of parms passed by invisible reference. */
|
||||
for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
|
||||
if (TREE_ADDRESSABLE (TREE_TYPE (t)))
|
||||
@ -1777,3 +1832,402 @@ cxx_omp_disregard_value_expr (tree decl, bool shared)
|
||||
&& DECL_LANG_SPECIFIC (decl)
|
||||
&& DECL_OMP_PRIVATIZED_MEMBER (decl);
|
||||
}
|
||||
|
||||
/* Callback for walk_tree, looking for LABEL_EXPR. Return *TP if it is
|
||||
a LABEL_EXPR; otherwise return NULL_TREE. Do not check the subtrees
|
||||
of GOTO_EXPR. */
|
||||
|
||||
static tree
|
||||
contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
switch (TREE_CODE (*tp))
|
||||
{
|
||||
case LABEL_EXPR:
|
||||
return *tp;
|
||||
|
||||
case GOTO_EXPR:
|
||||
*walk_subtrees = 0;
|
||||
|
||||
/* ... fall through ... */
|
||||
|
||||
default:
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return whether the sub-tree ST contains a label which is accessible from
|
||||
outside the sub-tree. */
|
||||
|
||||
static bool
|
||||
contains_label_p (tree st)
|
||||
{
|
||||
return
|
||||
walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE;
|
||||
}
|
||||
|
||||
/* Perform folding on expression X. */
|
||||
|
||||
tree
|
||||
cp_fully_fold (tree x)
|
||||
{
|
||||
return cp_fold (x);
|
||||
}
|
||||
|
||||
static GTY((cache, deletable)) cache_map fold_cache;
|
||||
|
||||
/* This function tries to fold an expression X.
|
||||
To avoid combinatorial explosion, folding results are kept in fold_cache.
|
||||
If we are processing a template or X is invalid, we don't fold at all.
|
||||
For performance reasons we don't cache expressions representing a
|
||||
declaration or constant.
|
||||
Function returns X or its folded variant. */
|
||||
|
||||
static tree
|
||||
cp_fold (tree x)
|
||||
{
|
||||
tree op0, op1, op2, op3;
|
||||
tree org_x = x, r = NULL_TREE;
|
||||
enum tree_code code;
|
||||
location_t loc;
|
||||
|
||||
if (!x || error_operand_p (x))
|
||||
return x;
|
||||
|
||||
if (processing_template_decl
|
||||
|| (EXPR_P (x) && !TREE_TYPE (x)))
|
||||
return x;
|
||||
|
||||
/* Don't bother to cache DECLs or constants. */
|
||||
if (DECL_P (x) || CONSTANT_CLASS_P (x))
|
||||
return x;
|
||||
|
||||
if (tree cached = fold_cache.get (x))
|
||||
return cached;
|
||||
|
||||
code = TREE_CODE (x);
|
||||
switch (code)
|
||||
{
|
||||
case SIZEOF_EXPR:
|
||||
x = fold_sizeof_expr (x);
|
||||
break;
|
||||
|
||||
case VIEW_CONVERT_EXPR:
|
||||
case CONVERT_EXPR:
|
||||
case NOP_EXPR:
|
||||
case NON_LVALUE_EXPR:
|
||||
|
||||
if (VOID_TYPE_P (TREE_TYPE (x)))
|
||||
return x;
|
||||
|
||||
if (!TREE_OPERAND (x, 0)
|
||||
|| TREE_CODE (TREE_OPERAND (x, 0)) == NON_LVALUE_EXPR)
|
||||
return x;
|
||||
|
||||
loc = EXPR_LOCATION (x);
|
||||
op0 = TREE_OPERAND (x, 0);
|
||||
|
||||
if (TREE_CODE (x) == NOP_EXPR
|
||||
&& TREE_OVERFLOW_P (op0)
|
||||
&& TREE_TYPE (x) == TREE_TYPE (op0))
|
||||
return x;
|
||||
|
||||
op0 = cp_fold (op0);
|
||||
|
||||
if (op0 != TREE_OPERAND (x, 0))
|
||||
x = build1_loc (loc, code, TREE_TYPE (x), op0);
|
||||
|
||||
x = fold (x);
|
||||
|
||||
/* Conversion of an out-of-range value has implementation-defined
|
||||
behavior; the language considers it different from arithmetic
|
||||
overflow, which is undefined. */
|
||||
if (TREE_CODE (op0) == INTEGER_CST
|
||||
&& TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0))
|
||||
TREE_OVERFLOW (x) = false;
|
||||
|
||||
break;
|
||||
|
||||
case SAVE_EXPR:
|
||||
case ADDR_EXPR:
|
||||
case REALPART_EXPR:
|
||||
case IMAGPART_EXPR:
|
||||
case CONJ_EXPR:
|
||||
case FIX_TRUNC_EXPR:
|
||||
case FLOAT_EXPR:
|
||||
case NEGATE_EXPR:
|
||||
case ABS_EXPR:
|
||||
case BIT_NOT_EXPR:
|
||||
case TRUTH_NOT_EXPR:
|
||||
case FIXED_CONVERT_EXPR:
|
||||
case UNARY_PLUS_EXPR:
|
||||
case INDIRECT_REF:
|
||||
|
||||
loc = EXPR_LOCATION (x);
|
||||
op0 = cp_fold (TREE_OPERAND (x, 0));
|
||||
|
||||
if (op0 != TREE_OPERAND (x, 0))
|
||||
x = build1_loc (loc, code, TREE_TYPE (x), op0);
|
||||
|
||||
x = fold (x);
|
||||
|
||||
gcc_assert (TREE_CODE (x) != COND_EXPR
|
||||
|| !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))));
|
||||
break;
|
||||
|
||||
case POSTDECREMENT_EXPR:
|
||||
case POSTINCREMENT_EXPR:
|
||||
case INIT_EXPR:
|
||||
|
||||
loc = EXPR_LOCATION (x);
|
||||
op0 = cp_fold (TREE_OPERAND (x, 0));
|
||||
op1 = cp_fold (TREE_OPERAND (x, 1));
|
||||
|
||||
if (TREE_OPERAND (x, 0) != op0 || TREE_OPERAND (x, 1) != op1)
|
||||
x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
|
||||
|
||||
break;
|
||||
|
||||
case PREDECREMENT_EXPR:
|
||||
case PREINCREMENT_EXPR:
|
||||
case COMPOUND_EXPR:
|
||||
case POINTER_PLUS_EXPR:
|
||||
case PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
case MULT_EXPR:
|
||||
case TRUNC_DIV_EXPR:
|
||||
case CEIL_DIV_EXPR:
|
||||
case FLOOR_DIV_EXPR:
|
||||
case ROUND_DIV_EXPR:
|
||||
case TRUNC_MOD_EXPR:
|
||||
case CEIL_MOD_EXPR:
|
||||
case ROUND_MOD_EXPR:
|
||||
case RDIV_EXPR:
|
||||
case EXACT_DIV_EXPR:
|
||||
case MIN_EXPR:
|
||||
case MAX_EXPR:
|
||||
case LSHIFT_EXPR:
|
||||
case RSHIFT_EXPR:
|
||||
case LROTATE_EXPR:
|
||||
case RROTATE_EXPR:
|
||||
case BIT_AND_EXPR:
|
||||
case BIT_IOR_EXPR:
|
||||
case BIT_XOR_EXPR:
|
||||
case TRUTH_AND_EXPR:
|
||||
case TRUTH_ANDIF_EXPR:
|
||||
case TRUTH_OR_EXPR:
|
||||
case TRUTH_ORIF_EXPR:
|
||||
case TRUTH_XOR_EXPR:
|
||||
case LT_EXPR: case LE_EXPR:
|
||||
case GT_EXPR: case GE_EXPR:
|
||||
case EQ_EXPR: case NE_EXPR:
|
||||
case UNORDERED_EXPR: case ORDERED_EXPR:
|
||||
case UNLT_EXPR: case UNLE_EXPR:
|
||||
case UNGT_EXPR: case UNGE_EXPR:
|
||||
case UNEQ_EXPR: case LTGT_EXPR:
|
||||
case RANGE_EXPR: case COMPLEX_EXPR:
|
||||
case MODIFY_EXPR:
|
||||
|
||||
loc = EXPR_LOCATION (x);
|
||||
op0 = cp_fold (TREE_OPERAND (x, 0));
|
||||
op1 = cp_fold (TREE_OPERAND (x, 1));
|
||||
if ((code == COMPOUND_EXPR || code == MODIFY_EXPR)
|
||||
&& ((op1 && TREE_SIDE_EFFECTS (op1))
|
||||
|| (op0 && TREE_SIDE_EFFECTS (op0))))
|
||||
break;
|
||||
if (TREE_CODE (x) == COMPOUND_EXPR && !op0)
|
||||
op0 = build_empty_stmt (loc);
|
||||
|
||||
if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
|
||||
x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
|
||||
|
||||
x = fold (x);
|
||||
|
||||
if (TREE_CODE (x) == COMPOUND_EXPR && TREE_OPERAND (x, 0) == NULL_TREE
|
||||
&& TREE_OPERAND (x, 1))
|
||||
return TREE_OPERAND (x, 1);
|
||||
break;
|
||||
|
||||
case VEC_COND_EXPR:
|
||||
case COND_EXPR:
|
||||
|
||||
loc = EXPR_LOCATION (x);
|
||||
op0 = cp_fold (TREE_OPERAND (x, 0));
|
||||
|
||||
if (TREE_SIDE_EFFECTS (op0))
|
||||
break;
|
||||
|
||||
op1 = cp_fold (TREE_OPERAND (x, 1));
|
||||
op2 = cp_fold (TREE_OPERAND (x, 2));
|
||||
|
||||
if (TREE_CODE (op0) == INTEGER_CST)
|
||||
{
|
||||
tree un;
|
||||
|
||||
if (integer_zerop (op0))
|
||||
{
|
||||
un = op1;
|
||||
r = op2;
|
||||
}
|
||||
else
|
||||
{
|
||||
un = op2;
|
||||
r = op1;
|
||||
}
|
||||
|
||||
if ((!TREE_SIDE_EFFECTS (un) || !contains_label_p (un))
|
||||
&& (! VOID_TYPE_P (TREE_TYPE (r)) || VOID_TYPE_P (x)))
|
||||
{
|
||||
if (CAN_HAVE_LOCATION_P (r)
|
||||
&& EXPR_LOCATION (r) != loc
|
||||
&& !(TREE_CODE (r) == SAVE_EXPR
|
||||
|| TREE_CODE (r) == TARGET_EXPR
|
||||
|| TREE_CODE (r) == BIND_EXPR))
|
||||
{
|
||||
r = copy_node (r);
|
||||
SET_EXPR_LOCATION (r, loc);
|
||||
}
|
||||
x = r;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (VOID_TYPE_P (TREE_TYPE (x)))
|
||||
break;
|
||||
|
||||
x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
|
||||
|
||||
if (code != COND_EXPR)
|
||||
x = fold (x);
|
||||
|
||||
break;
|
||||
|
||||
case CALL_EXPR:
|
||||
{
|
||||
int i, m, sv = optimize, nw = sv, changed = 0;
|
||||
tree callee = get_callee_fndecl (x);
|
||||
|
||||
if (callee && DECL_BUILT_IN (callee) && !optimize
|
||||
&& DECL_IS_BUILTIN_CONSTANT_P (callee)
|
||||
&& current_function_decl
|
||||
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
|
||||
nw = 1;
|
||||
optimize = nw;
|
||||
r = fold (x);
|
||||
optimize = sv;
|
||||
|
||||
if (TREE_CODE (r) != CALL_EXPR)
|
||||
{
|
||||
x = cp_fold (r);
|
||||
break;
|
||||
}
|
||||
|
||||
x = copy_node (x);
|
||||
|
||||
m = call_expr_nargs (x);
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
r = cp_fold (CALL_EXPR_ARG (x, i));
|
||||
if (r != CALL_EXPR_ARG (x, i))
|
||||
changed = 1;
|
||||
CALL_EXPR_ARG (x, i) = r;
|
||||
}
|
||||
|
||||
optimize = nw;
|
||||
r = fold (x);
|
||||
optimize = sv;
|
||||
|
||||
if (TREE_CODE (r) != CALL_EXPR)
|
||||
{
|
||||
x = cp_fold (r);
|
||||
break;
|
||||
}
|
||||
|
||||
optimize = nw;
|
||||
|
||||
/* Invoke maybe_constant_value for functions being declared
|
||||
constexpr, and are no AGGR_INIT_EXPRs ...
|
||||
TODO:
|
||||
Due issues in maybe_constant_value for CALL_EXPR with
|
||||
arguments passed by reference, it is disabled. */
|
||||
if (callee && DECL_DECLARED_CONSTEXPR_P (callee))
|
||||
r = maybe_constant_value (x);
|
||||
optimize = sv;
|
||||
|
||||
if (TREE_CODE (r) != CALL_EXPR)
|
||||
{
|
||||
x = r;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
x = org_x;
|
||||
break;
|
||||
}
|
||||
|
||||
case CONSTRUCTOR:
|
||||
{
|
||||
unsigned i;
|
||||
constructor_elt *p;
|
||||
vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (x);
|
||||
FOR_EACH_VEC_SAFE_ELT (elts, i, p)
|
||||
p->value = cp_fold (p->value);
|
||||
break;
|
||||
}
|
||||
case TREE_VEC:
|
||||
{
|
||||
bool changed = false;
|
||||
vec<tree, va_gc> *vec = make_tree_vector ();
|
||||
int i, n = TREE_VEC_LENGTH (x);
|
||||
vec_safe_reserve (vec, n);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
tree op = cp_fold (TREE_VEC_ELT (x, i));
|
||||
vec->quick_push (op);
|
||||
if (op != TREE_VEC_ELT (x, i))
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
r = copy_node (x);
|
||||
for (i = 0; i < n; i++)
|
||||
TREE_VEC_ELT (r, i) = (*vec)[i];
|
||||
x = r;
|
||||
}
|
||||
|
||||
release_tree_vector (vec);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ARRAY_REF:
|
||||
case ARRAY_RANGE_REF:
|
||||
|
||||
loc = EXPR_LOCATION (x);
|
||||
op0 = cp_fold (TREE_OPERAND (x, 0));
|
||||
op1 = cp_fold (TREE_OPERAND (x, 1));
|
||||
op2 = cp_fold (TREE_OPERAND (x, 2));
|
||||
op3 = cp_fold (TREE_OPERAND (x, 3));
|
||||
|
||||
if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1)
|
||||
|| op2 != TREE_OPERAND (x, 2) || op3 != TREE_OPERAND (x, 3))
|
||||
x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3);
|
||||
|
||||
x = fold (x);
|
||||
break;
|
||||
|
||||
default:
|
||||
return org_x;
|
||||
}
|
||||
|
||||
fold_cache.put (org_x, x);
|
||||
/* Prevent that we try to fold an already folded result again. */
|
||||
if (x != org_x)
|
||||
fold_cache.put (x, x);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
#include "gt-cp-cp-gimplify.h"
|
||||
|
@ -5447,6 +5447,42 @@ extern cp_parameter_declarator *no_parameters;
|
||||
/* True if we saw "#pragma GCC java_exceptions". */
|
||||
extern bool pragma_java_exceptions;
|
||||
|
||||
/* Data structure for a mapping from tree to tree that's only used as a cache;
|
||||
we don't GC-mark trees in the map, and we clear the map when collecting
|
||||
garbage. Global variables of this type must be marked
|
||||
GTY((cache,deletable)) so that the gt_cleare_cache function is called by
|
||||
ggc_collect but we don't try to load the map pointer from a PCH.
|
||||
|
||||
FIXME improve to use keep_cache_entry. */
|
||||
class cache_map
|
||||
{
|
||||
/* Use a lazily initialized pointer rather than a map member since a
|
||||
hash_map can't be constructed in a static initializer. */
|
||||
hash_map<tree, tree> *map;
|
||||
|
||||
public:
|
||||
tree get (tree key)
|
||||
{
|
||||
if (map)
|
||||
if (tree *slot = map->get (key))
|
||||
return *slot;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
bool put (tree key, tree val)
|
||||
{
|
||||
if (!map)
|
||||
map = new hash_map<tree, tree>;
|
||||
return map->put (key, val);
|
||||
}
|
||||
|
||||
friend inline void gt_cleare_cache (cache_map &cm)
|
||||
{
|
||||
if (cm.map)
|
||||
cm.map->empty();
|
||||
}
|
||||
};
|
||||
|
||||
/* in call.c */
|
||||
extern bool check_dtor_name (tree, tree);
|
||||
bool magic_varargs_p (tree);
|
||||
@ -6474,7 +6510,6 @@ extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
|
||||
walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
|
||||
#define cp_walk_tree_without_duplicates(tp,func,data) \
|
||||
walk_tree_without_duplicates_1 (tp, func, data, cp_walk_subtrees)
|
||||
extern tree fold_if_not_in_template (tree);
|
||||
extern tree rvalue (tree);
|
||||
extern tree convert_bitfield_to_declared_type (tree);
|
||||
extern tree cp_save_expr (tree);
|
||||
@ -6705,6 +6740,7 @@ extern tree cxx_omp_clause_dtor (tree, tree);
|
||||
extern void cxx_omp_finish_clause (tree, gimple_seq *);
|
||||
extern bool cxx_omp_privatize_by_reference (const_tree);
|
||||
extern bool cxx_omp_disregard_value_expr (tree, bool);
|
||||
extern tree cp_fully_fold (tree);
|
||||
|
||||
/* in name-lookup.c */
|
||||
extern void suggest_alternatives_for (location_t, tree);
|
||||
@ -6796,12 +6832,14 @@ 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 tree fold_simple (tree);
|
||||
extern bool is_sub_constant_expr (tree);
|
||||
extern bool reduced_constant_expression_p (tree);
|
||||
extern bool is_instantiation_of_constexpr (tree);
|
||||
extern bool var_in_constexpr_fn (tree);
|
||||
extern void explain_invalid_constexpr_fn (tree);
|
||||
extern vec<tree> cx_error_context (void);
|
||||
extern tree fold_sizeof_expr (tree);
|
||||
|
||||
/* In c-family/cilk.c */
|
||||
extern bool cilk_valid_spawn (tree);
|
||||
|
55
gcc/cp/cvt.c
55
gcc/cp/cvt.c
@ -50,7 +50,7 @@ static void diagnose_ref_binding (location_t, tree, tree, tree);
|
||||
|
||||
Here is a list of all the functions that assume that widening and
|
||||
narrowing is always done with a NOP_EXPR:
|
||||
In convert.c, convert_to_integer.
|
||||
In convert.c, convert_to_integer[_nofold].
|
||||
In c-typeck.c, build_binary_op_nodefault (boolean ops),
|
||||
and c_common_truthvalue_conversion.
|
||||
In expr.c: expand_expr, for operands of a MULT_EXPR.
|
||||
@ -237,7 +237,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
|
||||
gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
|
||||
== GET_MODE_SIZE (TYPE_MODE (type)));
|
||||
|
||||
return convert_to_pointer (type, expr);
|
||||
return convert_to_pointer_nofold (type, expr);
|
||||
}
|
||||
|
||||
if (type_unknown_p (expr))
|
||||
@ -630,22 +630,25 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
|
||||
|
||||
if (TREE_TYPE (expr) == type)
|
||||
return expr;
|
||||
|
||||
if (expr == error_mark_node)
|
||||
return expr;
|
||||
result = cp_convert (type, expr, complain);
|
||||
|
||||
if ((complain & tf_warning)
|
||||
&& c_inhibit_evaluation_warnings == 0)
|
||||
{
|
||||
tree folded = maybe_constant_value (expr);
|
||||
tree stripped = folded;
|
||||
tree folded_result
|
||||
= folded != expr ? cp_convert (type, folded, complain) : result;
|
||||
|
||||
/* maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW in a
|
||||
NOP_EXPR so that it isn't TREE_CONSTANT anymore. */
|
||||
STRIP_NOPS (stripped);
|
||||
|
||||
if (!TREE_OVERFLOW_P (stripped)
|
||||
tree folded = cp_fully_fold (expr);
|
||||
tree folded_result;
|
||||
if (folded == expr)
|
||||
folded_result = result;
|
||||
else
|
||||
{
|
||||
/* Avoid bogus -Wparentheses warnings. */
|
||||
TREE_NO_WARNING (folded) = true;
|
||||
folded_result = cp_convert (type, folded, tf_none);
|
||||
}
|
||||
folded_result = fold_simple (folded_result);
|
||||
if (!TREE_OVERFLOW_P (folded)
|
||||
&& folded_result != error_mark_node)
|
||||
warnings_for_convert_and_check (input_location, type, folded,
|
||||
folded_result);
|
||||
@ -703,9 +706,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
|
||||
/* For complex data types, we need to perform componentwise
|
||||
conversion. */
|
||||
else if (TREE_CODE (type) == COMPLEX_TYPE)
|
||||
return fold_if_not_in_template (convert_to_complex (type, e));
|
||||
return convert_to_complex_nofold (type, e);
|
||||
else if (VECTOR_TYPE_P (type))
|
||||
return fold_if_not_in_template (convert_to_vector (type, e));
|
||||
return convert_to_vector (type, e);
|
||||
else if (TREE_CODE (e) == TARGET_EXPR)
|
||||
{
|
||||
/* Don't build a NOP_EXPR of class type. Instead, change the
|
||||
@ -718,7 +721,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
|
||||
/* We shouldn't be treating objects of ADDRESSABLE type as
|
||||
rvalues. */
|
||||
gcc_assert (!TREE_ADDRESSABLE (type));
|
||||
return fold_if_not_in_template (build_nop (type, e));
|
||||
return build_nop (type, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,7 +799,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
|
||||
return cp_truthvalue_conversion (e);
|
||||
}
|
||||
|
||||
converted = fold_if_not_in_template (convert_to_integer (type, e));
|
||||
converted = convert_to_integer_nofold (type, e);
|
||||
|
||||
/* Ignore any integer overflow caused by the conversion. */
|
||||
return ignore_overflows (converted, e);
|
||||
@ -808,7 +811,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
|
||||
return nullptr_node;
|
||||
}
|
||||
if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type))
|
||||
return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain));
|
||||
return cp_convert_to_pointer (type, e, complain);
|
||||
if (code == VECTOR_TYPE)
|
||||
{
|
||||
tree in_vtype = TREE_TYPE (e);
|
||||
@ -823,7 +826,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
|
||||
in_vtype, type);
|
||||
return error_mark_node;
|
||||
}
|
||||
return fold_if_not_in_template (convert_to_vector (type, e));
|
||||
return convert_to_vector (type, e);
|
||||
}
|
||||
if (code == REAL_TYPE || code == COMPLEX_TYPE)
|
||||
{
|
||||
@ -839,9 +842,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
|
||||
TREE_TYPE (e));
|
||||
}
|
||||
if (code == REAL_TYPE)
|
||||
return fold_if_not_in_template (convert_to_real (type, e));
|
||||
return convert_to_real_nofold (type, e);
|
||||
else if (code == COMPLEX_TYPE)
|
||||
return fold_if_not_in_template (convert_to_complex (type, e));
|
||||
return convert_to_complex_nofold (type, e);
|
||||
}
|
||||
|
||||
/* New C++ semantics: since assignment is now based on
|
||||
@ -1454,7 +1457,7 @@ convert (tree type, tree expr)
|
||||
intype = TREE_TYPE (expr);
|
||||
|
||||
if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
|
||||
return fold_if_not_in_template (build_nop (type, expr));
|
||||
return build_nop (type, expr);
|
||||
|
||||
return ocp_convert (type, expr, CONV_OLD_CONVERT,
|
||||
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
|
||||
@ -1472,13 +1475,11 @@ convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain)
|
||||
enum tree_code code = TREE_CODE (type);
|
||||
|
||||
if (code == REFERENCE_TYPE)
|
||||
return (fold_if_not_in_template
|
||||
(convert_to_reference (type, e, CONV_C_CAST, 0,
|
||||
NULL_TREE, complain)));
|
||||
return convert_to_reference (type, e, CONV_C_CAST, 0,
|
||||
NULL_TREE, complain);
|
||||
|
||||
if (code == POINTER_TYPE)
|
||||
return fold_if_not_in_template (convert_to_pointer_force (type, e,
|
||||
complain));
|
||||
return convert_to_pointer_force (type, e, complain);
|
||||
|
||||
/* From typeck.c convert_for_assignment */
|
||||
if (((TYPE_PTR_P (TREE_TYPE (e)) && TREE_CODE (e) == ADDR_EXPR
|
||||
|
@ -8589,33 +8589,24 @@ stabilize_vla_size (tree size)
|
||||
cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
|
||||
}
|
||||
|
||||
/* Helper function for compute_array_index_type. Look for SIZEOF_EXPR
|
||||
not inside of SAVE_EXPR and fold them. */
|
||||
/* Reduce a SIZEOF_EXPR to its value. */
|
||||
|
||||
static tree
|
||||
fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
|
||||
tree
|
||||
fold_sizeof_expr (tree t)
|
||||
{
|
||||
tree expr = *expr_p;
|
||||
if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
|
||||
*walk_subtrees = 0;
|
||||
else if (TREE_CODE (expr) == SIZEOF_EXPR)
|
||||
{
|
||||
*(bool *)data = true;
|
||||
if (SIZEOF_EXPR_TYPE_P (expr))
|
||||
expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
|
||||
SIZEOF_EXPR, false);
|
||||
else if (TYPE_P (TREE_OPERAND (expr, 0)))
|
||||
expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
|
||||
false);
|
||||
else
|
||||
expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
|
||||
false);
|
||||
if (expr == error_mark_node)
|
||||
expr = size_one_node;
|
||||
*expr_p = expr;
|
||||
*walk_subtrees = 0;
|
||||
}
|
||||
return NULL;
|
||||
tree r;
|
||||
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;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Given the SIZE (i.e., number of elements) in an array, compute an
|
||||
@ -8708,7 +8699,18 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
|
||||
SET_TYPE_STRUCTURAL_EQUALITY (itype);
|
||||
return itype;
|
||||
}
|
||||
|
||||
|
||||
if (TREE_CODE (size) != INTEGER_CST)
|
||||
{
|
||||
tree folded = cp_fully_fold (size);
|
||||
if (TREE_CODE (folded) == INTEGER_CST)
|
||||
pedwarn (location_of (size), OPT_Wpedantic,
|
||||
"size of array is not an integral constant-expression");
|
||||
/* Use the folded result for VLAs, too; it will have resolved
|
||||
SIZEOF_EXPR. */
|
||||
size = folded;
|
||||
}
|
||||
|
||||
/* Normally, the array-bound will be a constant. */
|
||||
if (TREE_CODE (size) == INTEGER_CST)
|
||||
{
|
||||
@ -8795,7 +8797,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
|
||||
cp_convert (ssizetype, integer_one_node,
|
||||
complain),
|
||||
complain);
|
||||
itype = fold (itype);
|
||||
itype = maybe_constant_value (itype);
|
||||
processing_template_decl = saved_processing_template_decl;
|
||||
|
||||
if (!TREE_CONSTANT (itype))
|
||||
@ -8803,18 +8805,6 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
|
||||
/* A variable sized array. */
|
||||
itype = variable_size (itype);
|
||||
|
||||
if (TREE_CODE (itype) != SAVE_EXPR)
|
||||
{
|
||||
/* Look for SIZEOF_EXPRs in itype and fold them, otherwise
|
||||
they might survive till gimplification. */
|
||||
tree newitype = itype;
|
||||
bool found = false;
|
||||
cp_walk_tree_without_duplicates (&newitype,
|
||||
fold_sizeof_expr_r, &found);
|
||||
if (found)
|
||||
itype = variable_size (fold (newitype));
|
||||
}
|
||||
|
||||
stabilize_vla_size (itype);
|
||||
|
||||
if (flag_sanitize & SANITIZE_VLA
|
||||
@ -13514,7 +13504,7 @@ incremented enumerator value is too large for %<long%>");
|
||||
"type %<%T%>", value, ENUM_UNDERLYING_TYPE (enumtype));
|
||||
|
||||
/* Convert the value to the appropriate type. */
|
||||
value = convert (ENUM_UNDERLYING_TYPE (enumtype), value);
|
||||
value = fold_convert (ENUM_UNDERLYING_TYPE (enumtype), value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3112,7 +3112,7 @@ get_guard_cond (tree guard, bool thread_safe)
|
||||
{
|
||||
guard_value = integer_one_node;
|
||||
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
|
||||
guard_value = convert (TREE_TYPE (guard), guard_value);
|
||||
guard_value = fold_convert (TREE_TYPE (guard), guard_value);
|
||||
guard = cp_build_binary_op (input_location,
|
||||
BIT_AND_EXPR, guard, guard_value,
|
||||
tf_warning_or_error);
|
||||
@ -3120,7 +3120,7 @@ get_guard_cond (tree guard, bool thread_safe)
|
||||
|
||||
guard_value = integer_zero_node;
|
||||
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
|
||||
guard_value = convert (TREE_TYPE (guard), guard_value);
|
||||
guard_value = fold_convert (TREE_TYPE (guard), guard_value);
|
||||
return cp_build_binary_op (input_location,
|
||||
EQ_EXPR, guard, guard_value,
|
||||
tf_warning_or_error);
|
||||
@ -3138,7 +3138,7 @@ set_guard (tree guard)
|
||||
guard = get_guard_bits (guard);
|
||||
guard_init = integer_one_node;
|
||||
if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
|
||||
guard_init = convert (TREE_TYPE (guard), guard_init);
|
||||
guard_init = fold_convert (TREE_TYPE (guard), guard_init);
|
||||
return cp_build_modify_expr (guard, NOP_EXPR, guard_init,
|
||||
tf_warning_or_error);
|
||||
}
|
||||
|
@ -175,9 +175,9 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
|
||||
initialized are initialized to zero. */
|
||||
;
|
||||
else if (TYPE_PTR_OR_PTRMEM_P (type))
|
||||
init = convert (type, nullptr_node);
|
||||
init = fold (convert (type, nullptr_node));
|
||||
else if (SCALAR_TYPE_P (type))
|
||||
init = convert (type, integer_zero_node);
|
||||
init = fold (convert (type, integer_zero_node));
|
||||
else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type)))
|
||||
{
|
||||
tree field;
|
||||
@ -2558,6 +2558,11 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|
||||
outer_nelts_from_type = true;
|
||||
}
|
||||
|
||||
/* Lots of logic below. depends on whether we have a constant number of
|
||||
elements, so go ahead and fold it now. */
|
||||
if (outer_nelts)
|
||||
outer_nelts = maybe_constant_value (outer_nelts);
|
||||
|
||||
/* If our base type is an array, then make sure we know how many elements
|
||||
it has. */
|
||||
for (elt_type = type;
|
||||
@ -2608,7 +2613,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|
||||
/* Warn if we performed the (T[N]) to T[N] transformation and N is
|
||||
variable. */
|
||||
if (outer_nelts_from_type
|
||||
&& !TREE_CONSTANT (maybe_constant_value (outer_nelts)))
|
||||
&& !TREE_CONSTANT (outer_nelts))
|
||||
{
|
||||
if (complain & tf_warning_or_error)
|
||||
{
|
||||
@ -2708,7 +2713,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|
||||
max_outer_nelts = wi::udiv_trunc (max_size, inner_size);
|
||||
max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
|
||||
|
||||
size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
|
||||
size = size_binop (MULT_EXPR, size, fold_convert (sizetype, nelts));
|
||||
|
||||
if (TREE_CONSTANT (outer_nelts))
|
||||
{
|
||||
@ -2897,7 +2902,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|
||||
{
|
||||
placement_expr = get_target_expr (placement_first);
|
||||
CALL_EXPR_ARG (alloc_call, 1)
|
||||
= convert (TREE_TYPE (placement), placement_expr);
|
||||
= fold_convert (TREE_TYPE (placement), placement_expr);
|
||||
}
|
||||
|
||||
if (!member_new_p
|
||||
@ -3506,7 +3511,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
|
||||
|
||||
/* The below is short by the cookie size. */
|
||||
virtual_size = size_binop (MULT_EXPR, size_exp,
|
||||
convert (sizetype, maxindex));
|
||||
fold_convert (sizetype, maxindex));
|
||||
|
||||
tbase = create_temporary_var (ptype);
|
||||
tbase_init
|
||||
@ -3549,7 +3554,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
|
||||
|
||||
/* The below is short by the cookie size. */
|
||||
virtual_size = size_binop (MULT_EXPR, size_exp,
|
||||
convert (sizetype, maxindex));
|
||||
fold_convert (sizetype, maxindex));
|
||||
|
||||
if (! TYPE_VEC_NEW_USES_COOKIE (type))
|
||||
/* no header */
|
||||
@ -3595,8 +3600,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
|
||||
body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
|
||||
fold_build2_loc (input_location,
|
||||
NE_EXPR, boolean_type_node, base,
|
||||
convert (TREE_TYPE (base),
|
||||
nullptr_node)),
|
||||
fold_convert (TREE_TYPE (base),
|
||||
nullptr_node)),
|
||||
body, integer_zero_node);
|
||||
body = build1 (NOP_EXPR, void_type_node, body);
|
||||
|
||||
@ -3718,6 +3723,7 @@ build_vec_init (tree base, tree maxindex, tree init,
|
||||
if (maxindex == NULL_TREE || maxindex == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
maxindex = maybe_constant_value (maxindex);
|
||||
if (explicit_value_init_p)
|
||||
gcc_assert (!init);
|
||||
|
||||
@ -3759,6 +3765,8 @@ build_vec_init (tree base, tree maxindex, tree init,
|
||||
}
|
||||
|
||||
maxindex = cp_convert (ptrdiff_type_node, maxindex, complain);
|
||||
maxindex = fold_simple (maxindex);
|
||||
|
||||
if (TREE_CODE (atype) == ARRAY_TYPE)
|
||||
{
|
||||
ptype = build_pointer_type (type);
|
||||
|
@ -6778,7 +6778,7 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree *init_index,
|
||||
2. ARRAY [ EXP : EXP ]
|
||||
3. ARRAY [ EXP : EXP : EXP ] */
|
||||
|
||||
*init_index = cp_parser_expression (parser);
|
||||
*init_index = cp_parser_expression (parser);
|
||||
if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
|
||||
{
|
||||
/* This indicates that we have a normal array expression. */
|
||||
@ -8522,9 +8522,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
|
||||
/* For "false && x" or "true || x", x will never be executed;
|
||||
disable warnings while evaluating it. */
|
||||
if (current.tree_type == TRUTH_ANDIF_EXPR)
|
||||
c_inhibit_evaluation_warnings += current.lhs == truthvalue_false_node;
|
||||
c_inhibit_evaluation_warnings +=
|
||||
cp_fully_fold (current.lhs) == truthvalue_false_node;
|
||||
else if (current.tree_type == TRUTH_ORIF_EXPR)
|
||||
c_inhibit_evaluation_warnings += current.lhs == truthvalue_true_node;
|
||||
c_inhibit_evaluation_warnings +=
|
||||
cp_fully_fold (current.lhs) == truthvalue_true_node;
|
||||
|
||||
/* Extract another operand. It may be the RHS of this expression
|
||||
or the LHS of a new, higher priority expression. */
|
||||
@ -8571,9 +8573,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
|
||||
|
||||
/* Undo the disabling of warnings done above. */
|
||||
if (current.tree_type == TRUTH_ANDIF_EXPR)
|
||||
c_inhibit_evaluation_warnings -= current.lhs == truthvalue_false_node;
|
||||
c_inhibit_evaluation_warnings -=
|
||||
cp_fully_fold (current.lhs) == truthvalue_false_node;
|
||||
else if (current.tree_type == TRUTH_ORIF_EXPR)
|
||||
c_inhibit_evaluation_warnings -= current.lhs == truthvalue_true_node;
|
||||
c_inhibit_evaluation_warnings -=
|
||||
cp_fully_fold (current.lhs) == truthvalue_true_node;
|
||||
|
||||
if (warn_logical_not_paren
|
||||
&& TREE_CODE_CLASS (current.tree_type) == tcc_comparison
|
||||
@ -8659,7 +8663,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
|
||||
static tree
|
||||
cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
|
||||
{
|
||||
tree expr;
|
||||
tree expr, folded_logical_or_expr = cp_fully_fold (logical_or_expr);
|
||||
tree assignment_expr;
|
||||
struct cp_token *token;
|
||||
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
|
||||
@ -8674,7 +8678,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
|
||||
"ISO C++ does not allow ?: with omitted middle operand");
|
||||
/* Implicit true clause. */
|
||||
expr = NULL_TREE;
|
||||
c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
|
||||
c_inhibit_evaluation_warnings +=
|
||||
folded_logical_or_expr == truthvalue_true_node;
|
||||
warn_for_omitted_condop (token->location, logical_or_expr);
|
||||
}
|
||||
else
|
||||
@ -8682,11 +8687,12 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
|
||||
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
|
||||
parser->colon_corrects_to_scope_p = false;
|
||||
/* Parse the expression. */
|
||||
c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
|
||||
c_inhibit_evaluation_warnings +=
|
||||
folded_logical_or_expr == truthvalue_false_node;
|
||||
expr = cp_parser_expression (parser);
|
||||
c_inhibit_evaluation_warnings +=
|
||||
((logical_or_expr == truthvalue_true_node)
|
||||
- (logical_or_expr == truthvalue_false_node));
|
||||
((folded_logical_or_expr == truthvalue_true_node)
|
||||
- (folded_logical_or_expr == truthvalue_false_node));
|
||||
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
|
||||
}
|
||||
|
||||
@ -8694,7 +8700,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
|
||||
cp_parser_require (parser, CPP_COLON, RT_COLON);
|
||||
/* Parse the assignment-expression. */
|
||||
assignment_expr = cp_parser_assignment_expression (parser);
|
||||
c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
|
||||
c_inhibit_evaluation_warnings -=
|
||||
folded_logical_or_expr == truthvalue_true_node;
|
||||
|
||||
/* Build the conditional-expression. */
|
||||
return build_x_conditional_expr (loc, logical_or_expr,
|
||||
|
@ -6211,7 +6211,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
|
||||
/* 14.3.2/5: The null pointer{,-to-member} conversion is applied
|
||||
to a non-type argument of "nullptr". */
|
||||
if (expr == nullptr_node && TYPE_PTR_OR_PTRMEM_P (type))
|
||||
expr = convert (type, expr);
|
||||
expr = fold_simple (convert (type, expr));
|
||||
|
||||
/* In C++11, integral or enumeration non-type template arguments can be
|
||||
arbitrary constant expressions. Pointer and pointer to
|
||||
|
@ -2562,9 +2562,26 @@ finish_unary_op_expr (location_t loc, enum tree_code code, tree expr,
|
||||
tsubst_flags_t complain)
|
||||
{
|
||||
tree result = build_x_unary_op (loc, code, expr, complain);
|
||||
if ((complain & tf_warning)
|
||||
&& TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
|
||||
overflow_warning (input_location, result);
|
||||
tree result_ovl, expr_ovl;
|
||||
|
||||
if (!(complain & tf_warning))
|
||||
return result;
|
||||
|
||||
result_ovl = result;
|
||||
expr_ovl = expr;
|
||||
|
||||
if (!processing_template_decl)
|
||||
expr_ovl = cp_fully_fold (expr_ovl);
|
||||
|
||||
if (!CONSTANT_CLASS_P (expr_ovl)
|
||||
|| TREE_OVERFLOW_P (expr_ovl))
|
||||
return result;
|
||||
|
||||
if (!processing_template_decl)
|
||||
result_ovl = cp_fully_fold (result_ovl);
|
||||
|
||||
if (CONSTANT_CLASS_P (result_ovl) && TREE_OVERFLOW_P (result_ovl))
|
||||
overflow_warning (input_location, result_ovl);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -4476,6 +4493,11 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
|
||||
low_bound = mark_rvalue_use (low_bound);
|
||||
if (length)
|
||||
length = mark_rvalue_use (length);
|
||||
/* We need to reduce to real constant-values for checks below. */
|
||||
if (length)
|
||||
length = fold_simple (length);
|
||||
if (low_bound)
|
||||
low_bound = fold_simple (low_bound);
|
||||
if (low_bound
|
||||
&& TREE_CODE (low_bound) == INTEGER_CST
|
||||
&& TYPE_PRECISION (TREE_TYPE (low_bound))
|
||||
@ -7440,6 +7462,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
|
||||
if (init && EXPR_HAS_LOCATION (init))
|
||||
elocus = EXPR_LOCATION (init);
|
||||
|
||||
cond = cp_fully_fold (cond);
|
||||
switch (TREE_CODE (cond))
|
||||
{
|
||||
case GT_EXPR:
|
||||
@ -7475,6 +7498,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
|
||||
diff = build_x_binary_op (elocus, MINUS_EXPR, TREE_OPERAND (cond, 1),
|
||||
ERROR_MARK, iter, ERROR_MARK, NULL,
|
||||
tf_warning_or_error);
|
||||
diff = cp_fully_fold (diff);
|
||||
if (error_operand_p (diff))
|
||||
return true;
|
||||
if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE)
|
||||
@ -7536,7 +7560,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
|
||||
if (TREE_CODE (rhs) == MINUS_EXPR)
|
||||
{
|
||||
incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr);
|
||||
incr = fold_if_not_in_template (incr);
|
||||
incr = fold_simple (incr);
|
||||
}
|
||||
if (TREE_CODE (incr) != INTEGER_CST
|
||||
&& (TREE_CODE (incr) != NOP_EXPR
|
||||
|
@ -303,9 +303,19 @@ xvalue_p (const_tree ref)
|
||||
bool
|
||||
builtin_valid_in_constant_expr_p (const_tree decl)
|
||||
{
|
||||
/* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
|
||||
in constant-expressions. We may want to add other builtins later. */
|
||||
return DECL_IS_BUILTIN_CONSTANT_P (decl);
|
||||
if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)))
|
||||
/* Not a built-in. */
|
||||
return false;
|
||||
switch (DECL_FUNCTION_CODE (decl))
|
||||
{
|
||||
case BUILT_IN_CONSTANT_P:
|
||||
case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
|
||||
/* These have constant results even if their operands are
|
||||
non-constant. */
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build a TARGET_EXPR, initializing the DECL with the VALUE. */
|
||||
@ -681,8 +691,8 @@ convert_bitfield_to_declared_type (tree expr)
|
||||
|
||||
bitfield_type = is_bitfield_expr_with_lowered_type (expr);
|
||||
if (bitfield_type)
|
||||
expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
|
||||
expr);
|
||||
expr = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type),
|
||||
expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@ -3479,10 +3489,13 @@ handle_init_priority_attribute (tree* node,
|
||||
|
||||
STRIP_NOPS (initp_expr);
|
||||
initp_expr = default_conversion (initp_expr);
|
||||
if (initp_expr)
|
||||
initp_expr = maybe_constant_value (initp_expr);
|
||||
|
||||
if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
|
||||
{
|
||||
error ("requested init_priority is not an integer constant");
|
||||
cxx_constant_value (initp_expr);
|
||||
*no_add_attrs = true;
|
||||
return NULL_TREE;
|
||||
}
|
||||
@ -4257,26 +4270,6 @@ stabilize_init (tree init, tree *initp)
|
||||
return !TREE_SIDE_EFFECTS (init);
|
||||
}
|
||||
|
||||
/* Like "fold", but should be used whenever we might be processing the
|
||||
body of a template. */
|
||||
|
||||
tree
|
||||
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 instantiate_non_dependent_expr, as necessary. */
|
||||
if (processing_template_decl)
|
||||
return expr;
|
||||
|
||||
/* Fold C++ front-end specific tree codes. */
|
||||
if (TREE_CODE (expr) == UNARY_PLUS_EXPR)
|
||||
return fold_convert (TREE_TYPE (expr), TREE_OPERAND (expr, 0));
|
||||
|
||||
return fold (expr);
|
||||
}
|
||||
|
||||
/* Returns true if a cast to TYPE may appear in an integral constant
|
||||
expression. */
|
||||
|
||||
|
127
gcc/cp/typeck.c
127
gcc/cp/typeck.c
@ -1945,8 +1945,6 @@ decay_conversion (tree exp,
|
||||
|
||||
code = TREE_CODE (type);
|
||||
|
||||
/* FIXME remove for delayed folding. */
|
||||
exp = scalar_constant_value (exp);
|
||||
if (error_operand_p (exp))
|
||||
return error_mark_node;
|
||||
|
||||
@ -2439,7 +2437,6 @@ build_class_member_access_expr (tree object, tree member,
|
||||
|
||||
result = build3_loc (input_location, COMPONENT_REF, member_type,
|
||||
object, member, NULL_TREE);
|
||||
result = fold_if_not_in_template (result);
|
||||
|
||||
/* Mark the expression const or volatile, as appropriate. Even
|
||||
though we've dealt with the type above, we still have to mark the
|
||||
@ -2852,9 +2849,9 @@ build_simple_component_ref (tree object, tree member)
|
||||
{
|
||||
tree type = cp_build_qualified_type (TREE_TYPE (member),
|
||||
cp_type_quals (TREE_TYPE (object)));
|
||||
return fold_build3_loc (input_location,
|
||||
COMPONENT_REF, type,
|
||||
object, member, NULL_TREE);
|
||||
return build3_loc (input_location,
|
||||
COMPONENT_REF, type,
|
||||
object, member, NULL_TREE);
|
||||
}
|
||||
|
||||
/* Return an expression for the MEMBER_NAME field in the internal
|
||||
@ -3173,8 +3170,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
|
||||
|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
|
||||
TREE_THIS_VOLATILE (rval)
|
||||
|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
|
||||
ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
|
||||
complain);
|
||||
ret = require_complete_type_sfinae (rval, complain);
|
||||
protected_set_expr_location (ret, loc);
|
||||
if (non_lvalue)
|
||||
ret = non_lvalue_loc (loc, ret);
|
||||
@ -3921,7 +3917,6 @@ build_vec_cmp (tree_code code, tree type,
|
||||
tree minus_one_vec = build_minus_one_cst (type);
|
||||
tree cmp_type = build_same_sized_truth_vector_type(type);
|
||||
tree cmp = build2 (code, cmp_type, arg0, arg1);
|
||||
cmp = fold_if_not_in_template (cmp);
|
||||
return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
|
||||
}
|
||||
|
||||
@ -3976,7 +3971,7 @@ cp_build_binary_op (location_t location,
|
||||
convert it to this type. */
|
||||
tree final_type = 0;
|
||||
|
||||
tree result;
|
||||
tree result, result_ovl;
|
||||
tree orig_type = NULL;
|
||||
|
||||
/* Nonzero if this is an operation like MIN or MAX which can
|
||||
@ -4599,7 +4594,7 @@ cp_build_binary_op (location_t location,
|
||||
op0 = cp_build_binary_op (location,
|
||||
TRUTH_ANDIF_EXPR, e1, e2,
|
||||
complain);
|
||||
op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain);
|
||||
op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4640,10 +4635,12 @@ cp_build_binary_op (location_t location,
|
||||
op1 = save_expr (op1);
|
||||
|
||||
pfn0 = pfn_from_ptrmemfunc (op0);
|
||||
pfn0 = cp_fully_fold (pfn0);
|
||||
/* Avoid -Waddress warnings (c++/64877). */
|
||||
if (TREE_CODE (pfn0) == ADDR_EXPR)
|
||||
TREE_NO_WARNING (pfn0) = 1;
|
||||
pfn1 = pfn_from_ptrmemfunc (op1);
|
||||
pfn1 = cp_fully_fold (pfn1);
|
||||
delta0 = delta_from_ptrmemfunc (op0);
|
||||
delta1 = delta_from_ptrmemfunc (op1);
|
||||
if (TARGET_PTRMEMFUNC_VBIT_LOCATION
|
||||
@ -4997,10 +4994,7 @@ cp_build_binary_op (location_t location,
|
||||
gcc_unreachable();
|
||||
}
|
||||
}
|
||||
real = fold_if_not_in_template (real);
|
||||
imag = fold_if_not_in_template (imag);
|
||||
result = build2 (COMPLEX_EXPR, result_type, real, imag);
|
||||
result = fold_if_not_in_template (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -5028,20 +5022,12 @@ cp_build_binary_op (location_t location,
|
||||
|
||||
if (short_compare)
|
||||
{
|
||||
/* Don't write &op0, etc., because that would prevent op0
|
||||
from being kept in a register.
|
||||
Instead, make copies of the our local variables and
|
||||
pass the copies by reference, then copy them back afterward. */
|
||||
tree xop0 = op0, xop1 = op1, xresult_type = result_type;
|
||||
/* We call shorten_compare only for diagnostic-reason. */
|
||||
tree xop0 = fold_simple (op0), xop1 = fold_simple (op1),
|
||||
xresult_type = result_type;
|
||||
enum tree_code xresultcode = resultcode;
|
||||
tree val
|
||||
= shorten_compare (location, &xop0, &xop1, &xresult_type,
|
||||
shorten_compare (location, &xop0, &xop1, &xresult_type,
|
||||
&xresultcode);
|
||||
if (val != 0)
|
||||
return cp_convert (boolean_type_node, val, complain);
|
||||
op0 = xop0, op1 = xop1;
|
||||
converted = 1;
|
||||
resultcode = xresultcode;
|
||||
}
|
||||
|
||||
if ((short_compare || code == MIN_EXPR || code == MAX_EXPR)
|
||||
@ -5060,9 +5046,9 @@ cp_build_binary_op (location_t location,
|
||||
tree oop1 = maybe_constant_value (orig_op1);
|
||||
|
||||
if (TREE_CODE (oop0) != INTEGER_CST)
|
||||
oop0 = orig_op0;
|
||||
oop0 = cp_fully_fold (orig_op0);
|
||||
if (TREE_CODE (oop1) != INTEGER_CST)
|
||||
oop1 = orig_op1;
|
||||
oop1 = cp_fully_fold (orig_op1);
|
||||
warn_for_sign_compare (location, oop0, oop1, op0, op1,
|
||||
result_type, resultcode);
|
||||
}
|
||||
@ -5117,18 +5103,30 @@ cp_build_binary_op (location_t location,
|
||||
}
|
||||
|
||||
result = build2 (resultcode, build_type, op0, op1);
|
||||
result = fold_if_not_in_template (result);
|
||||
if (final_type != 0)
|
||||
result = cp_convert (final_type, result, complain);
|
||||
|
||||
if (TREE_OVERFLOW_P (result)
|
||||
&& !TREE_OVERFLOW_P (op0)
|
||||
&& !TREE_OVERFLOW_P (op1))
|
||||
overflow_warning (location, result);
|
||||
|
||||
if (instrument_expr != NULL)
|
||||
result = fold_build2 (COMPOUND_EXPR, TREE_TYPE (result),
|
||||
instrument_expr, result);
|
||||
result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
|
||||
instrument_expr, result);
|
||||
|
||||
if (!processing_template_decl)
|
||||
{
|
||||
op0 = cp_fully_fold (op0);
|
||||
/* Only consider the second argument if the first isn't overflowed. */
|
||||
if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0))
|
||||
return result;
|
||||
op1 = cp_fully_fold (op1);
|
||||
if (!CONSTANT_CLASS_P (op1) || TREE_OVERFLOW_P (op1))
|
||||
return result;
|
||||
}
|
||||
else if (!CONSTANT_CLASS_P (op0) || !CONSTANT_CLASS_P (op1)
|
||||
|| TREE_OVERFLOW_P (op0) || TREE_OVERFLOW_P (op1))
|
||||
return result;
|
||||
|
||||
result_ovl = fold_build2 (resultcode, build_type, op0, op1);
|
||||
if (TREE_OVERFLOW_P (result_ovl))
|
||||
overflow_warning (location, result_ovl);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -5178,8 +5176,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop,
|
||||
complete_type (TREE_TYPE (res_type));
|
||||
|
||||
return pointer_int_sum (input_location, resultcode, ptrop,
|
||||
fold_if_not_in_template (intop),
|
||||
complain & tf_warning_or_error);
|
||||
intop, complain & tf_warning_or_error);
|
||||
}
|
||||
|
||||
/* Return a tree for the difference of pointers OP0 and OP1.
|
||||
@ -5255,7 +5252,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain)
|
||||
|
||||
result = build2 (EXACT_DIV_EXPR, restype, op0,
|
||||
cp_convert (restype, op1, complain));
|
||||
return fold_if_not_in_template (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Construct and perhaps optimize a tree representation
|
||||
@ -5771,6 +5768,10 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
|
||||
/* Make sure the result is not an lvalue: a unary plus or minus
|
||||
expression is always a rvalue. */
|
||||
arg = rvalue (arg);
|
||||
|
||||
if (code == NEGATE_EXPR && CONSTANT_CLASS_P (arg))
|
||||
/* Immediately fold negation of a constant. */
|
||||
return fold_build1 (code, TREE_TYPE (arg), arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -5835,10 +5836,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
|
||||
case REALPART_EXPR:
|
||||
case IMAGPART_EXPR:
|
||||
arg = build_real_imag_expr (input_location, code, arg);
|
||||
if (arg == error_mark_node)
|
||||
return arg;
|
||||
else
|
||||
return fold_if_not_in_template (arg);
|
||||
return arg;
|
||||
|
||||
case PREINCREMENT_EXPR:
|
||||
case POSTINCREMENT_EXPR:
|
||||
@ -6005,7 +6003,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
|
||||
{
|
||||
if (argtype == 0)
|
||||
argtype = TREE_TYPE (arg);
|
||||
return fold_if_not_in_template (build1 (code, argtype, arg));
|
||||
return build1 (code, argtype, arg);
|
||||
}
|
||||
|
||||
if (complain & tf_error)
|
||||
@ -6999,7 +6997,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|
||||
return rvalue (expr);
|
||||
else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
|
||||
|| (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
|
||||
return fold_if_not_in_template (build_nop (type, expr));
|
||||
return build_nop (type, expr);
|
||||
else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype))
|
||||
|| (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
|
||||
{
|
||||
@ -7027,7 +7025,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|
||||
if (warn_strict_aliasing <= 2)
|
||||
strict_aliasing_warning (intype, type, sexpr);
|
||||
|
||||
return fold_if_not_in_template (build_nop (type, expr));
|
||||
return build_nop (type, expr);
|
||||
}
|
||||
else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
|
||||
|| (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
|
||||
@ -7038,13 +7036,13 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|
||||
warning (OPT_Wconditionally_supported,
|
||||
"casting between pointer-to-function and pointer-to-object "
|
||||
"is conditionally-supported");
|
||||
return fold_if_not_in_template (build_nop (type, expr));
|
||||
return build_nop (type, expr);
|
||||
}
|
||||
else if (VECTOR_TYPE_P (type))
|
||||
return fold_if_not_in_template (convert_to_vector (type, expr));
|
||||
return convert_to_vector (type, expr);
|
||||
else if (VECTOR_TYPE_P (intype)
|
||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (type))
|
||||
return fold_if_not_in_template (convert_to_integer (type, expr));
|
||||
return convert_to_integer_nofold (type, expr);
|
||||
else
|
||||
{
|
||||
if (valid_p)
|
||||
@ -7896,8 +7894,7 @@ get_delta_difference (tree from, tree to,
|
||||
}
|
||||
}
|
||||
|
||||
return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node,
|
||||
result));
|
||||
return convert_to_integer (ptrdiff_type_node, result);
|
||||
}
|
||||
|
||||
/* Return a constructor for the pointer-to-member-function TYPE using
|
||||
@ -8078,41 +8075,35 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
|
||||
fn; the call will do the opposite adjustment. */
|
||||
tree orig_class = DECL_CONTEXT (fn);
|
||||
tree binfo = binfo_or_else (orig_class, fn_class);
|
||||
*delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
|
||||
*delta, BINFO_OFFSET (binfo));
|
||||
*delta = fold_if_not_in_template (*delta);
|
||||
*delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
|
||||
*delta, BINFO_OFFSET (binfo));
|
||||
|
||||
/* We set PFN to the vtable offset at which the function can be
|
||||
found, plus one (unless ptrmemfunc_vbit_in_delta, in which
|
||||
case delta is shifted left, and then incremented). */
|
||||
*pfn = DECL_VINDEX (fn);
|
||||
*pfn = build2 (MULT_EXPR, integer_type_node, *pfn,
|
||||
TYPE_SIZE_UNIT (vtable_entry_type));
|
||||
*pfn = fold_if_not_in_template (*pfn);
|
||||
*pfn = fold_build2 (MULT_EXPR, integer_type_node, *pfn,
|
||||
TYPE_SIZE_UNIT (vtable_entry_type));
|
||||
|
||||
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
|
||||
{
|
||||
case ptrmemfunc_vbit_in_pfn:
|
||||
*pfn = build2 (PLUS_EXPR, integer_type_node, *pfn,
|
||||
integer_one_node);
|
||||
*pfn = fold_if_not_in_template (*pfn);
|
||||
*pfn = fold_build2 (PLUS_EXPR, integer_type_node, *pfn,
|
||||
integer_one_node);
|
||||
break;
|
||||
|
||||
case ptrmemfunc_vbit_in_delta:
|
||||
*delta = build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
|
||||
*delta, integer_one_node);
|
||||
*delta = fold_if_not_in_template (*delta);
|
||||
*delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
|
||||
*delta, integer_one_node);
|
||||
*delta = fold_if_not_in_template (*delta);
|
||||
*delta = fold_build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
|
||||
*delta, integer_one_node);
|
||||
*delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
|
||||
*delta, integer_one_node);
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
*pfn = build_nop (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
|
||||
*pfn = fold_if_not_in_template (*pfn);
|
||||
*pfn = fold_convert (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -738,6 +738,7 @@ split_nonconstant_init (tree dest, tree init)
|
||||
init = TARGET_EXPR_INITIAL (init);
|
||||
if (TREE_CODE (init) == CONSTRUCTOR)
|
||||
{
|
||||
init = cp_fully_fold (init);
|
||||
code = push_stmt_list ();
|
||||
if (split_nonconstant_init_1 (dest, init))
|
||||
init = NULL_TREE;
|
||||
@ -828,6 +829,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
|
||||
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
|
||||
TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
|
||||
}
|
||||
value = cp_fully_fold (value);
|
||||
|
||||
if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
|
||||
/* Handle aggregate NSDMI in non-constant initializers, too. */
|
||||
@ -926,19 +928,35 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
|
||||
}
|
||||
}
|
||||
|
||||
bool almost_ok = ok;
|
||||
if (!ok && !CONSTANT_CLASS_P (init) && (complain & tf_warning_or_error))
|
||||
{
|
||||
tree folded = cp_fully_fold (init);
|
||||
if (TREE_CONSTANT (folded) && check_narrowing (type, folded, tf_none))
|
||||
almost_ok = true;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
location_t loc = EXPR_LOC_OR_LOC (init, input_location);
|
||||
if (cxx_dialect == cxx98)
|
||||
warning_at (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
|
||||
"narrowing conversion of %qE from %qT to %qT inside { } "
|
||||
"is ill-formed in C++11", init, ftype, type);
|
||||
else if (!TREE_CONSTANT (init))
|
||||
{
|
||||
if (complain & tf_warning)
|
||||
warning_at (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
|
||||
"from %qT to %qT inside { } is ill-formed in C++11",
|
||||
init, ftype, type);
|
||||
ok = true;
|
||||
}
|
||||
else if (!CONSTANT_CLASS_P (init))
|
||||
{
|
||||
if (complain & tf_warning_or_error)
|
||||
{
|
||||
pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
|
||||
"narrowing conversion of %qE from %qT to %qT inside { }",
|
||||
init, ftype, type);
|
||||
if (!almost_ok || pedantic)
|
||||
pedwarn (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
|
||||
"from %qT to %qT inside { }", init, ftype, type);
|
||||
if (pedantic && almost_ok)
|
||||
inform (loc, " the expression has a constant value but is not "
|
||||
"a C++ constant-expression");
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
@ -946,7 +964,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
|
||||
{
|
||||
int savederrorcount = errorcount;
|
||||
global_dc->pedantic_errors = 1;
|
||||
pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
|
||||
pedwarn (loc, OPT_Wnarrowing,
|
||||
"narrowing conversion of %qE from %qT to %qT "
|
||||
"inside { }", init, ftype, type);
|
||||
if (errorcount == savederrorcount)
|
||||
@ -955,7 +973,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
|
||||
}
|
||||
}
|
||||
|
||||
return cxx_dialect == cxx98 || ok;
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Process the initializer INIT for a variable of type TYPE, emitting
|
||||
|
@ -1,3 +1,7 @@
|
||||
2015-11-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* config-lang.in (gtfiles): Add cp-gimplify.c.
|
||||
|
||||
2015-11-11 Andrew MacLeod <amacleod@redhat.com>
|
||||
|
||||
* objcp-decl.c: Remove unused header files.
|
||||
|
@ -45,6 +45,6 @@ subdir_requires="objc cp"
|
||||
|
||||
# This list is separated in two parts: the first one is identical to
|
||||
# the C++ one, the second one contains our ObjC++ additions.
|
||||
gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \
|
||||
gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c \
|
||||
\$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
|
||||
|
||||
|
@ -47,3 +47,5 @@ right (int x)
|
||||
r += -1U >> x;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
|
||||
|
@ -47,3 +47,6 @@ right (int x)
|
||||
r += -1U >> x;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
|
||||
/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
|
||||
|
@ -47,3 +47,6 @@ right (int x)
|
||||
r += -1U >> x;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
|
||||
/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
|
||||
|
@ -47,3 +47,6 @@ right (int x)
|
||||
r += -1U >> x;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
|
||||
/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-do compile { target { c } } } */
|
||||
/* { dg-options "-fdump-tree-original" } */
|
||||
/* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
|
||||
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
{
|
||||
/* I am surprised this is considered a constexpr */
|
||||
return *((Inner *)4);
|
||||
} // { dg-error "reinterpret_cast" "" { xfail *-*-* } }
|
||||
} // { dg-error "reinterpret_cast" "" }
|
||||
};
|
||||
|
||||
B B::instance;
|
||||
|
29
gcc/testsuite/g++.dg/cpp0x/pr53792.C
Normal file
29
gcc/testsuite/g++.dg/cpp0x/pr53792.C
Normal file
@ -0,0 +1,29 @@
|
||||
// PR c++/53792
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2 -fdump-tree-optimized" }
|
||||
// { dg-final { scan-tree-dump "return 0" "optimized" } }
|
||||
|
||||
struct entry {
|
||||
char const* label;
|
||||
int value;
|
||||
};
|
||||
|
||||
constexpr bool same(char const *x, char const *y) {
|
||||
return !*x && !*y ? true
|
||||
: /* default */ (*x == *y && same(x+1, y+1));
|
||||
}
|
||||
|
||||
constexpr int keyToValue(char const *label, entry const *entries) {
|
||||
return !entries->label ? entries->value
|
||||
: same(entries->label, label) ? entries->value
|
||||
: /*default*/ keyToValue(label, entries+1);
|
||||
}
|
||||
|
||||
constexpr entry foo[] = {{"Foo", 0}, {"Bar", 1}, {"FooBar", 2}, {0, -1}};
|
||||
|
||||
int
|
||||
bar()
|
||||
{
|
||||
int result = keyToValue("Foo", foo);
|
||||
return result;
|
||||
}
|
14
gcc/testsuite/g++.dg/cpp0x/pr56868.cpp
Normal file
14
gcc/testsuite/g++.dg/cpp0x/pr56868.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
constexpr int f(void *) { return 0; }
|
||||
constexpr int f(...) { return 1; }
|
||||
constexpr int g1() { return f(0); }
|
||||
constexpr int g2(int n) { return f(n); }
|
||||
constexpr int g3(int n) { return f(n*0); }
|
||||
|
||||
int main()
|
||||
{
|
||||
static_assert(g1() == 0, "g1 failed");
|
||||
static_assert(g2(0) == 1, "g2 failed");
|
||||
static_assert(g3(0) == 1, "g3 failed");
|
||||
}
|
12
gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C
Normal file
@ -0,0 +1,12 @@
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2 -Woverflow" }
|
||||
|
||||
#include <climits>
|
||||
|
||||
constexpr int f() { return INT_MIN; }
|
||||
|
||||
int main()
|
||||
{
|
||||
return -f(); // { dg-warning "overflow" }
|
||||
}
|
||||
|
12
gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C
Normal file
@ -0,0 +1,12 @@
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2 -Woverflow" }
|
||||
|
||||
#include <climits>
|
||||
|
||||
constexpr int f() { return INT_MAX; }
|
||||
|
||||
int main()
|
||||
{
|
||||
return f() + 2; // { dg-warning "overflow" }
|
||||
}
|
||||
|
13
gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C
Normal file
13
gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C
Normal file
@ -0,0 +1,13 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wall -Werror" } */
|
||||
|
||||
extern int fl;
|
||||
|
||||
#define MAK (fl < 0 ? 1 : (fl ? -1 : 0))
|
||||
|
||||
int foo (int sz)
|
||||
{
|
||||
if (MAK) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
17
gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C
Normal file
17
gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C
Normal file
@ -0,0 +1,17 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wall -Werror" } */
|
||||
|
||||
extern int fl;
|
||||
extern int arr[];
|
||||
|
||||
#define MAK (fl < 0 ? 1 : (fl ? 2 : 0))
|
||||
|
||||
int foo (int sz)
|
||||
{
|
||||
unsigned i;
|
||||
int r = 0;
|
||||
for (i = 0; i < MAK; i++)
|
||||
r += arr[i];
|
||||
return r;
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
template<typename T>
|
||||
void type_alignment(const T&) {
|
||||
struct { char c; T t; } s;
|
||||
SA((char*)&s.t - (char*)&s.c == 1);
|
||||
struct S { char c; T t; } s;
|
||||
SA(__builtin_offsetof (S,t) - __builtin_offsetof (S,c) == 1);
|
||||
}
|
||||
|
||||
template <class T> struct A { char c; T t; };
|
||||
@ -17,7 +17,8 @@ int main() {
|
||||
|
||||
A<aligned> a; // { dg-warning "ignoring attributes" }
|
||||
|
||||
SA((char*)&a.t - (char*)&a.c == 1);
|
||||
SA( __builtin_offsetof (__typeof(a),t)
|
||||
- __builtin_offsetof (__typeof(a),c) == 1);
|
||||
|
||||
aligned z;
|
||||
type_alignment(z); // { dg-warning "ignoring attributes" "" { xfail *-*-* } }
|
||||
|
@ -1,6 +1,7 @@
|
||||
// PR c++/27601
|
||||
// Origin: Patrik Hägglund <patrik.hagglund@bredband.net>
|
||||
// { dg-do compile }
|
||||
// { dg-options "-Wno-pointer-arith" }
|
||||
|
||||
struct bar {
|
||||
static int foo;
|
||||
@ -10,7 +11,7 @@ struct bar {
|
||||
int a = __builtin_offsetof(bar, foo); // { dg-error "static data member" }
|
||||
int av = __builtin_offsetof(volatile bar, foo); // { dg-error "static data member" }
|
||||
int b = __builtin_offsetof(bar, baz); // { dg-error "member function" }
|
||||
int b0 = __builtin_offsetof(bar, baz[0]); // { dg-error "function" }
|
||||
int b0 = __builtin_offsetof(bar, baz[0]); // { dg-error "single identifier nor|member function" }
|
||||
int bv0 = __builtin_offsetof(volatile bar, baz[0]); // { dg-error "function" }
|
||||
int c = __builtin_offsetof(bar, ~bar); // { dg-error "member function" }
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fdump-tree-gimple" }
|
||||
// { dg-options "-fdump-tree-gimple -pedantic" }
|
||||
|
||||
struct s { int x, y; };
|
||||
short offsets[1] = {
|
||||
((char*) &(((struct s*)16)->y) - (char *)16),
|
||||
((char*) &(((struct s*)16)->y) - (char *)16), // { dg-message "narrowing" "" { target c++11 } }
|
||||
};
|
||||
|
||||
// This ensures that we get a dump whether or not the bug is present.
|
||||
|
@ -10,7 +10,7 @@ void f(__SIZE_TYPE__) {
|
||||
|
||||
int main()
|
||||
{
|
||||
int* const savepos = sizeof(*savepos) ? 0 : 0;
|
||||
int* const savepos = sizeof(*savepos) ? 0 : 0; /* { dg-error "invalid conversion" "convert" { target c++11 } } */
|
||||
|
||||
f (sizeof (*savepos));
|
||||
|
||||
|
@ -5,5 +5,5 @@ extern "C" double fabs (double);
|
||||
|
||||
void foo (double x)
|
||||
{
|
||||
fabs (x) (); // { dg-error "__builtin_abs" }
|
||||
fabs (x) (); // { dg-error "function" }
|
||||
}
|
||||
|
@ -8,6 +8,6 @@ void
|
||||
bar (int i, int j, double k)
|
||||
{
|
||||
foo (i && j) (); // { dg-error "\\(\\(?i != 0\\)? \\&\\& \\(?j != 0\\)?\\)" }
|
||||
foo (!i || !j) (); // { dg-error "\\(\\(?i == 0\\)? \\|\\| \\(?j == 0\\)?\\)" }
|
||||
foo (!i == !j) (); // { dg-error "\\(\\(?i != 0\\)? \\^ \\(?j == 0\\)?\\)" }
|
||||
foo (!i || !j) (); // { dg-error "function" }
|
||||
foo (!i == !j) (); // { dg-error "function" }
|
||||
}
|
||||
|
@ -2,5 +2,5 @@
|
||||
|
||||
void foo(__complex__ double x)
|
||||
{
|
||||
__builtin_conj(x)(); // { dg-error "~x" }
|
||||
__builtin_conj(x)(); // { dg-error "function" }
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ extern void bar (char *, char *);
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
char g[(char *) &((struct S *) 0)->b - (char *) 0];
|
||||
char h[(__SIZE_TYPE__) &((struct S *) 8)->b];
|
||||
char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" }
|
||||
char h[(__SIZE_TYPE__) &((struct S *) 8)->b]; // { dg-error "constant" "" { xfail *-*-* } }
|
||||
bar (g, h);
|
||||
}
|
||||
|
@ -1,14 +1,10 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-fsanitize=integer-divide-by-zero" } */
|
||||
|
||||
/* TODO: We expect an error on the invalid case here, because that
|
||||
must be a constant-expression. This will be fixed when we have
|
||||
proper delayed folding. */
|
||||
|
||||
void
|
||||
foo (int i)
|
||||
{
|
||||
switch (i)
|
||||
case 0 * (1 / 0): /* { dg-warning "division by zero" } */
|
||||
; /* { dg-error "division by zero" "" { xfail *-*-* } 10 } */
|
||||
; /* { dg-error "is not a constant.expression" "" { target *-*-* } 8 } */
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ foo (int x)
|
||||
/* None of the following should pass. */
|
||||
switch (x)
|
||||
{
|
||||
case 1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
|
||||
case -1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
|
||||
case 1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
|
||||
case -1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
|
||||
case 1 >> -1: /* { dg-error "operand of shift" "" } */
|
||||
case -1 >> -1: /* { dg-error "operand of shift" "" } */
|
||||
case 1 << -1: /* { dg-error "operand of shift" "" } */
|
||||
case -1 << -1: /* { dg-error "operand of shift" "" } */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -23,8 +23,8 @@ bar (int x)
|
||||
/* None of the following should pass. */
|
||||
switch (x)
|
||||
{
|
||||
case -1 >> 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
|
||||
case 1 << 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
|
||||
case -1 >> 200: /* { dg-error "operand of shift" "" } */
|
||||
case 1 << 200: /* { dg-error "operand of shift" "" } */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -17,7 +17,7 @@ enum e {
|
||||
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
|
||||
whole expression violates the constraints. */
|
||||
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
|
||||
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
|
||||
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
|
||||
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
|
||||
/* Again, overflow in evaluated subexpression. */
|
||||
@ -126,3 +126,11 @@ h2i (int x)
|
||||
ui = INT_MIN;
|
||||
ui = x ? INT_MIN : 1U;
|
||||
}
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
|
||||
/* { dg-warning "invalid conversion from" "convert" { target *-*-* } 56 } */
|
||||
/* { dg-warning "invalid conversion from" "convert" { target c++11 } 58 } */
|
||||
/* { dg-error "is not a constant expression" "const" { target *-*-* } 65 } */
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 65 } */
|
||||
/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
|
||||
/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
|
||||
|
@ -17,7 +17,7 @@ enum e {
|
||||
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
|
||||
whole expression violates the constraints. */
|
||||
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
|
||||
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
|
||||
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
|
||||
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
|
||||
/* Again, overflow in evaluated subexpression. */
|
||||
@ -56,7 +56,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
|
||||
/* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 55 } */
|
||||
|
||||
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
|
||||
/* { dg-warning "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */
|
||||
/* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
|
||||
void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
|
||||
|
||||
void
|
||||
@ -65,7 +65,7 @@ g (int i)
|
||||
switch (i)
|
||||
{
|
||||
case 0 * (1/0): /* { dg-warning "division by zero" } */
|
||||
;
|
||||
; /* { dg-error "is not a constant expression" "const" { target *-*-* } 67 } */
|
||||
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 69 } */
|
||||
;
|
||||
@ -128,3 +128,9 @@ h2i (int x)
|
||||
ui = INT_MIN;
|
||||
ui = x ? INT_MIN : 1U;
|
||||
}
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
|
||||
/* { dg-warning "invalid conversion from" "convert" { target c++11 } 60 } */
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 67 } */
|
||||
/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
|
||||
/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
|
||||
|
@ -17,7 +17,7 @@ enum e {
|
||||
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
|
||||
whole expression violates the constraints. */
|
||||
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
|
||||
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
|
||||
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
|
||||
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
|
||||
/* { dg-error "enumerator value for 'E5' is not an integer constant" "enum error" { target *-*-* } 21 } */
|
||||
@ -59,7 +59,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
|
||||
/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
|
||||
|
||||
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
|
||||
/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 61 } */
|
||||
/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 61 } */
|
||||
void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
|
||||
|
||||
void
|
||||
@ -68,7 +68,7 @@ g (int i)
|
||||
switch (i)
|
||||
{
|
||||
case 0 * (1/0): /* { dg-warning "division by zero" } */
|
||||
;
|
||||
; /* { dg-error "is not a constant expression" "const" { target *-*-* } 70 } */
|
||||
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 72 } */
|
||||
;
|
||||
@ -131,3 +131,9 @@ h2i (int x)
|
||||
ui = INT_MIN;
|
||||
ui = x ? INT_MIN : 1U;
|
||||
}
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
|
||||
/* { dg-error "invalid conversion from" "convert" { target c++11 } 63 } */
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 34 } */
|
||||
/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 70 } */
|
||||
/* { dg-error "width not an integer constant" "bit.field" { target c++ } 34 } */
|
||||
/* { dg-error "is not a constant expression" "division" { target c++ } 34 } */
|
||||
|
@ -3,5 +3,5 @@
|
||||
void x()
|
||||
{
|
||||
int* p = 1==0; // { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
|
||||
// { dg-error "cannot convert" "" { target c++11 } 5 }
|
||||
// { dg-error "cannot convert" "" { target { c++11 } } 5 }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user