aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-10-07 15:28:36 -0700
committerIan Lance Taylor <iant@golang.org>2021-10-07 15:28:36 -0700
commit0b6b70a0733672600644c8df96942cda5bf86d3d (patch)
tree9a1fbd7f782c54df55ab225ed1be057e3f3b0b8a /gcc/c-family
parenta5b5cabc91c38710adbe5c8a2b53882abe994441 (diff)
parentfba228e259dd5112851527f2dbb62c5601100985 (diff)
downloadgcc-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/ChangeLog72
-rw-r--r--gcc/c-family/c-common.c47
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/c-family/c-cppbuiltin.c4
-rw-r--r--gcc/c-family/c-format.c2
-rw-r--r--gcc/c-family/c-omp.c56
-rw-r--r--gcc/c-family/c-opts.c1
-rw-r--r--gcc/c-family/c-ubsan.c49
-rw-r--r--gcc/c-family/c-warn.c32
-rw-r--r--gcc/c-family/c.opt4
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.