diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-10-07 15:28:36 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-10-07 15:28:36 -0700 |
commit | 0b6b70a0733672600644c8df96942cda5bf86d3d (patch) | |
tree | 9a1fbd7f782c54df55ab225ed1be057e3f3b0b8a /gcc/c-family | |
parent | a5b5cabc91c38710adbe5c8a2b53882abe994441 (diff) | |
parent | fba228e259dd5112851527f2dbb62c5601100985 (diff) | |
download | gcc-0b6b70a0733672600644c8df96942cda5bf86d3d.zip gcc-0b6b70a0733672600644c8df96942cda5bf86d3d.tar.gz gcc-0b6b70a0733672600644c8df96942cda5bf86d3d.tar.bz2 |
Merge from trunk revision fba228e259dd5112851527f2dbb62c5601100985.
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 72 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 47 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c-family/c-cppbuiltin.c | 4 | ||||
-rw-r--r-- | gcc/c-family/c-format.c | 2 | ||||
-rw-r--r-- | gcc/c-family/c-omp.c | 56 | ||||
-rw-r--r-- | gcc/c-family/c-opts.c | 1 | ||||
-rw-r--r-- | gcc/c-family/c-ubsan.c | 49 | ||||
-rw-r--r-- | gcc/c-family/c-warn.c | 32 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 4 |
10 files changed, 246 insertions, 22 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 9c59035..a6484f4 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,75 @@ +2021-10-06 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/102571 + * c-omp.c (c_finish_omp_atomic): Optimize the case where type has + padding, but the non-padding bits are contiguous set of bytes + by adjusting the memcmp call arguments instead of emitting + __builtin_clear_padding and then comparing all the type's bytes. + +2021-10-06 Jakub Jelinek <jakub@redhat.com> + + PR c++/102612 + * c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine + __cpp_constexpr to 202110L rather than 201907L. + +2021-10-04 Marek Polacek <polacek@redhat.com> + + PR c++/97573 + * c-common.h (do_warn_array_compare): Declare. + * c-warn.c (do_warn_array_compare): New. + * c.opt (Warray-compare): New option. + +2021-10-02 Iain Sandoe <iain@sandoe.co.uk> + + * c-format.c: Remove a test of TARGET_FORMAT_TYPES with + NULL, this is not needed. + +2021-10-01 Martin Sebor <msebor@redhat.com> + + PR c/102103 + * c-common.c (decl_with_nonnull_addr_p): Handle members. + Check and perform warning suppression. + (c_common_truthvalue_conversion): Enhance warning suppression. + +2021-10-01 Martin Liska <mliska@suse.cz> + + PR target/102552 + * c-common.c (parse_optimize_options): decoded_options[0] is + used for program name, so merged_decoded_options should also + respect that. + +2021-10-01 Jakub Jelinek <jakub@redhat.com> + Richard Biener <rguenther@suse.de> + + PR sanitizer/102515 + * c-ubsan.c (ubsan_instrument_division): Check the right + flag_sanitize_recover bit, depending on which sanitization + is done. Sanitize INT_MIN / -1 under SANITIZE_SI_OVERFLOW + rather than SANITIZE_DIVIDE. If both SANITIZE_SI_OVERFLOW + and SANITIZE_DIVIDE is enabled, neither check is known + to be false and flag_sanitize_recover bits for those two + aren't the same, emit both __ubsan_handle_divrem_overflow + and __ubsan_handle_divrem_overflow_abort calls. + +2021-10-01 Martin Liska <mliska@suse.cz> + + * c-common.c (parse_optimize_options): Combine optimize + options with what was provided on the command line. + +2021-10-01 Jakub Jelinek <jakub@redhat.com> + + * c-omp.c (c_omp_split_clauses): Also copy + OMP_CLAUSE_ORDER_REPRODUCIBLE. + +2021-09-27 Martin Liska <mliska@suse.cz> + + * c-opts.c (c_common_init_options_struct): Set also + x_flag_default_complex_method. + +2021-09-22 Jakub Jelinek <jakub@redhat.com> + + * c-omp.c (c_omp_split_clauses): Copy over OMP_CLAUSE_ALLOCATE_ALIGN. + 2021-09-20 Matthias Kretz <m.kretz@gsi.de> * c-cppbuiltin.c (c_cpp_builtins_optimize_pragma): Define or diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index c6757f0..32c7e3e 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -3393,14 +3393,16 @@ c_wrap_maybe_const (tree expr, bool non_const) return expr; } -/* Return whether EXPR is a declaration whose address can never be - NULL. */ +/* Return whether EXPR is a declaration whose address can never be NULL. + The address of the first struct member could be NULL only if it were + accessed through a NULL pointer, and such an access would be invalid. */ bool decl_with_nonnull_addr_p (const_tree expr) { return (DECL_P (expr) - && (TREE_CODE (expr) == PARM_DECL + && (TREE_CODE (expr) == FIELD_DECL + || TREE_CODE (expr) == PARM_DECL || TREE_CODE (expr) == LABEL_DECL || !DECL_WEAK (expr))); } @@ -3488,13 +3490,17 @@ c_common_truthvalue_conversion (location_t location, tree expr) case ADDR_EXPR: { tree inner = TREE_OPERAND (expr, 0); - if (decl_with_nonnull_addr_p (inner)) + if (decl_with_nonnull_addr_p (inner) + /* Check both EXPR and INNER for suppression. */ + && !warning_suppressed_p (expr, OPT_Waddress) + && !warning_suppressed_p (inner, OPT_Waddress)) { - /* Common Ada programmer's mistake. */ + /* Common Ada programmer's mistake. */ warning_at (location, OPT_Waddress, "the address of %qD will always evaluate as %<true%>", inner); + suppress_warning (inner, OPT_Waddress); return truthvalue_true_node; } break; @@ -3627,8 +3633,17 @@ c_common_truthvalue_conversion (location_t location, tree expr) break; /* If this isn't narrowing the argument, we can ignore it. */ if (TYPE_PRECISION (totype) >= TYPE_PRECISION (fromtype)) - return c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 0)); + { + tree op0 = TREE_OPERAND (expr, 0); + if ((TREE_CODE (fromtype) == POINTER_TYPE + && TREE_CODE (totype) == INTEGER_TYPE) + || warning_suppressed_p (expr, OPT_Waddress)) + /* Suppress -Waddress for casts to intptr_t, propagating + any suppression from the enclosing expression to its + operand. */ + suppress_warning (op0, OPT_Waddress); + return c_common_truthvalue_conversion (location, op0); + } } break; @@ -5904,9 +5919,23 @@ parse_optimize_options (tree args, bool attr_p) j++; } decoded_options_count = j; - /* And apply them. */ + + /* Merge the decoded options with save_decoded_options. */ + unsigned save_opt_count = save_opt_decoded_options->length (); + unsigned merged_decoded_options_count + = save_opt_count + decoded_options_count; + cl_decoded_option *merged_decoded_options + = XNEWVEC (cl_decoded_option, merged_decoded_options_count); + + /* Note the first decoded_options is used for the program name. */ + for (unsigned i = 0; i < save_opt_count; ++i) + merged_decoded_options[i + 1] = (*save_opt_decoded_options)[i]; + for (unsigned i = 1; i < decoded_options_count; ++i) + merged_decoded_options[save_opt_count + i] = decoded_options[i]; + + /* And apply them. */ decode_options (&global_options, &global_options_set, - decoded_options, decoded_options_count, + merged_decoded_options, merged_decoded_options_count, input_location, global_dc, NULL); free (decoded_options); diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 849cefa..078730f 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1421,6 +1421,7 @@ extern bool warn_for_restrict (unsigned, tree *, unsigned); extern void warn_for_address_or_pointer_of_packed_member (tree, tree); extern void warn_parm_array_mismatch (location_t, tree, tree); extern void maybe_warn_sizeof_array_div (location_t, tree, tree, tree, tree); +extern void do_warn_array_compare (location_t, tree_code, tree, tree); /* Places where an lvalue, or modifiable lvalue, may be required. Used to select diagnostic messages in lvalue_error and diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index a299273..60e9e05 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -1052,7 +1052,8 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__cpp_init_captures=201803L"); cpp_define (pfile, "__cpp_generic_lambdas=201707L"); cpp_define (pfile, "__cpp_designated_initializers=201707L"); - cpp_define (pfile, "__cpp_constexpr=201907L"); + if (cxx_dialect <= cxx20) + cpp_define (pfile, "__cpp_constexpr=201907L"); cpp_define (pfile, "__cpp_constexpr_in_decltype=201711L"); cpp_define (pfile, "__cpp_conditional_explicit=201806L"); cpp_define (pfile, "__cpp_consteval=201811L"); @@ -1071,6 +1072,7 @@ c_cpp_builtins (cpp_reader *pfile) /* Set feature test macros for C++23. */ cpp_define (pfile, "__cpp_size_t_suffix=202011L"); cpp_define (pfile, "__cpp_if_consteval=202106L"); + cpp_define (pfile, "__cpp_constexpr=202110L"); } if (flag_concepts) { diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index b4cb765a..ca66c81 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -5150,7 +5150,7 @@ handle_format_attribute (tree *node, tree atname, tree args, #ifdef TARGET_FORMAT_TYPES /* If the target provides additional format types, we need to add them to FORMAT_TYPES at first use. */ - if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types) + if (!dynamic_format_types) { dynamic_format_types = XNEWVEC (format_kind_info, n_format_types + TARGET_N_FORMAT_TYPES); diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index b606cf4..d8b9855 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -379,6 +379,8 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, if (SCALAR_FLOAT_TYPE_P (cmptype) && !test) { bool clear_padding = false; + HOST_WIDE_INT non_padding_start = 0; + HOST_WIDE_INT non_padding_end = 0; if (BITS_PER_UNIT == 8 && CHAR_BIT == 8) { HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i; @@ -392,6 +394,40 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, clear_padding = true; break; } + if (clear_padding && buf[i] == 0) + { + /* Try to optimize. In the common case where + non-padding bits are all continuous and start + and end at a byte boundary, we can just adjust + the memcmp call arguments and don't need to + emit __builtin_clear_padding calls. */ + if (i == 0) + { + for (i = 0; i < sz; i++) + if (buf[i] != 0) + break; + if (i < sz && buf[i] == (unsigned char) ~0) + { + non_padding_start = i; + for (; i < sz; i++) + if (buf[i] != (unsigned char) ~0) + break; + } + else + i = 0; + } + if (i != 0) + { + non_padding_end = i; + for (; i < sz; i++) + if (buf[i] != 0) + { + non_padding_start = 0; + non_padding_end = 0; + break; + } + } + } } tree inttype = NULL_TREE; if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype))) @@ -428,12 +464,22 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, tmp2 = build4 (TARGET_EXPR, cmptype, tmp2, TREE_OPERAND (rhs1, 1), NULL, NULL); tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2); + if (non_padding_start) + { + tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1, + size_int (non_padding_start)); + tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2, + size_int (non_padding_start)); + } tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP); rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2, - TYPE_SIZE_UNIT (cmptype)); + non_padding_end + ? size_int (non_padding_end + - non_padding_start) + : TYPE_SIZE_UNIT (cmptype)); rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1, integer_zero_node); - if (clear_padding) + if (clear_padding && non_padding_end == 0) { fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING); tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1); @@ -2128,6 +2174,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, OMP_CLAUSE_ORDER); OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses); + OMP_CLAUSE_ORDER_REPRODUCIBLE (c) + = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c; } @@ -2139,6 +2187,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, OMP_CLAUSE_ORDER); OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses); + OMP_CLAUSE_ORDER_REPRODUCIBLE (c) + = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c; s = C_OMP_CLAUSE_SPLIT_SIMD; @@ -2511,6 +2561,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, = OMP_CLAUSE_DECL (clauses); OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses); + OMP_CLAUSE_ALLOCATE_ALIGN (c) + = OMP_CLAUSE_ALLOCATE_ALIGN (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[s]; cclauses[s] = c; has_dup_allocate = true; diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index fdde082..3eaab5e 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -222,6 +222,7 @@ c_common_init_options_struct (struct gcc_options *opts) /* By default, C99-like requirements for complex multiply and divide. */ opts->x_flag_complex_method = 2; + opts->x_flag_default_complex_method = opts->x_flag_complex_method; } /* Common initialization before calling option handlers. */ diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index 12a7bca..a4509c6 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -39,8 +39,9 @@ along with GCC; see the file COPYING3. If not see tree ubsan_instrument_division (location_t loc, tree op0, tree op1) { - tree t, tt; + tree t, tt, x = NULL_TREE; tree type = TREE_TYPE (op0); + enum sanitize_code flag = SANITIZE_DIVIDE; /* At this point both operands should have the same type, because they are already converted to RESULT_TYPE. @@ -58,24 +59,42 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) op1, build_int_cst (type, 0)); else if (TREE_CODE (type) == REAL_TYPE && sanitize_flags_p (SANITIZE_FLOAT_DIVIDE)) - t = fold_build2 (EQ_EXPR, boolean_type_node, - op1, build_real (type, dconst0)); + { + t = fold_build2 (EQ_EXPR, boolean_type_node, + op1, build_real (type, dconst0)); + flag = SANITIZE_FLOAT_DIVIDE; + } else - return NULL_TREE; + t = NULL_TREE; /* We check INT_MIN / -1 only for signed types. */ if (TREE_CODE (type) == INTEGER_TYPE - && sanitize_flags_p (SANITIZE_DIVIDE) + && sanitize_flags_p (SANITIZE_SI_OVERFLOW) && !TYPE_UNSIGNED (type)) { - tree x; tt = fold_build2 (EQ_EXPR, boolean_type_node, unshare_expr (op1), build_int_cst (type, -1)); x = fold_build2 (EQ_EXPR, boolean_type_node, op0, TYPE_MIN_VALUE (type)); x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt); - t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x); + if (t == NULL_TREE || integer_zerop (t)) + { + t = x; + x = NULL_TREE; + flag = SANITIZE_SI_OVERFLOW; + } + else if (flag_sanitize_undefined_trap_on_error + || (((flag_sanitize_recover & SANITIZE_DIVIDE) == 0) + == ((flag_sanitize_recover & SANITIZE_SI_OVERFLOW) == 0))) + { + t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x); + x = NULL_TREE; + } + else if (integer_zerop (x)) + x = NULL_TREE; } + else if (t == NULL_TREE) + return NULL_TREE; /* If the condition was folded to 0, no need to instrument this expression. */ @@ -95,7 +114,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) NULL_TREE); data = build_fold_addr_expr_loc (loc, data); enum built_in_function bcode - = (flag_sanitize_recover & SANITIZE_DIVIDE) + = (flag_sanitize_recover & flag) ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT; tt = builtin_decl_explicit (bcode); @@ -103,8 +122,20 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) op1 = unshare_expr (op1); tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0), ubsan_encode_value (op1)); + if (x) + { + bcode = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW) + ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW + : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT; + tree xt = builtin_decl_explicit (bcode); + op0 = unshare_expr (op0); + op1 = unshare_expr (op1); + xt = build_call_expr_loc (loc, xt, 3, data, ubsan_encode_value (op0), + ubsan_encode_value (op1)); + x = fold_build3 (COND_EXPR, void_type_node, x, xt, void_node); + } } - t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node); + t = fold_build3 (COND_EXPR, void_type_node, t, tt, x ? x : void_node); return t; } diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 84ad663..99cde4a 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -3726,3 +3726,35 @@ maybe_warn_sizeof_array_div (location_t loc, tree arr, tree arr_type, } } } + +/* Warn about C++20 [depr.array.comp] array comparisons: "Equality + and relational comparisons between two operands of array type are + deprecated." We also warn in C and earlier C++ standards. CODE is + the code for this comparison, OP0 and OP1 are the operands. */ + +void +do_warn_array_compare (location_t location, tree_code code, tree op0, tree op1) +{ + STRIP_NOPS (op0); + STRIP_NOPS (op1); + if (TREE_CODE (op0) == ADDR_EXPR) + op0 = TREE_OPERAND (op0, 0); + if (TREE_CODE (op1) == ADDR_EXPR) + op1 = TREE_OPERAND (op1, 0); + + auto_diagnostic_group d; + if (warning_at (location, OPT_Warray_compare, + (c_dialect_cxx () && cxx_dialect >= cxx20) + ? G_("comparison between two arrays is deprecated in C++20") + : G_("comparison between two arrays"))) + { + /* C doesn't allow +arr. */ + if (c_dialect_cxx ()) + inform (location, "use unary %<+%> which decays operands to pointers " + "or %<&%D[0] %s &%D[0]%> to compare the addresses", + op0, op_symbol_code (code), op1); + else + inform (location, "use %<&%D[0] %s &%D[0]%> to compare the addresses", + op0, op_symbol_code (code), op1); + } +} diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 9c151d1..06457ac 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -350,6 +350,10 @@ Warray-bounds= LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0) ; in common.opt +Warray-compare +C ObjC C++ ObjC++ Var(warn_array_compare) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall) +Warn about comparisons between two operands of array type. + Warray-parameter C ObjC C++ ObjC++ Warning Alias(Warray-parameter=, 2, 0) Warn about mismatched declarations of array parameters and unsafe accesses to them. |