aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
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
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')
-rw-r--r--gcc/c/ChangeLog44
-rw-r--r--gcc/c/c-parser.c169
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/c/c-typeck.c171
-rw-r--r--gcc/c/gimple-parser.c14
5 files changed, 340 insertions, 60 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 794cbe7..24096bb 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,47 @@
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR c/102605
+ * gimple-parser.c (c_parser_gimple_postfix_expression):
+ Accept more address _Literals.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-typeck.c (parser_build_binary_op): Call do_warn_array_compare.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * c-typeck.c (maybe_warn_for_null_address): New function.
+ (build_binary_op): Call it.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * c-typeck.c (build_binary_op): Call ubsan_instrument_division
+ for division even for SANITIZE_SI_OVERFLOW.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_order): Set
+ OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
+
+2021-09-28 Andrew Pinski <apinski@marvell.com>
+
+ PR c/32122
+ * c-parser.c (c_parser_statement_after_labels): Pass
+ the c_expr instead of the tree to c_finish_goto_ptr.
+ * c-typeck.c (c_finish_goto_ptr): Change the second
+ argument type to c_expr.
+ * c-tree.h (c_finish_goto_ptr): Likewise.
+ Error out if the expression was not of a pointer type.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_allocate): Parse allocate clause
+ modifiers.
+
2021-09-18 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (c_parser_omp_clause_order): Parse unconstrained
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fb1399e..a66f43f 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -6141,7 +6141,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_consume_token (parser);
val = c_parser_expression (parser);
val = convert_lvalue_to_rvalue (loc, val, false, true);
- stmt = c_finish_goto_ptr (loc, val.value);
+ stmt = c_finish_goto_ptr (loc, val);
}
else
c_parser_error (parser, "expected identifier or %<*%>");
@@ -14626,6 +14626,7 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
tree c;
const char *p;
bool unconstrained = false;
+ bool reproducible = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -14636,7 +14637,9 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp (p, "unconstrained") == 0)
unconstrained = true;
- else if (strcmp (p, "reproducible") != 0)
+ else if (strcmp (p, "reproducible") == 0)
+ reproducible = true;
+ else
{
c_parser_error (parser, "expected %<reproducible%> or "
"%<unconstrained%>");
@@ -14661,6 +14664,7 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -15305,7 +15309,15 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
/* OpenMP 5.0:
allocate ( variable-list )
- allocate ( expression : variable-list ) */
+ allocate ( expression : variable-list )
+
+ OpenMP 5.1:
+ allocate ( allocator-modifier : variable-list )
+ allocate ( allocator-modifier , allocator-modifier : variable-list )
+
+ allocator-modifier:
+ allocator ( expression )
+ align ( expression ) */
static tree
c_parser_omp_clause_allocate (c_parser *parser, tree list)
@@ -15313,6 +15325,7 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
location_t clause_loc = c_parser_peek_token (parser)->location;
tree nl, c;
tree allocator = NULL_TREE;
+ tree align = NULL_TREE;
matching_parens parens;
if (!parens.require_open (parser))
@@ -15323,17 +15336,128 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
|| (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
&& c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
{
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- allocator = expr.value;
- allocator = c_fully_fold (allocator, false, NULL);
- tree orig_type
- = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
- orig_type = TYPE_MAIN_VARIANT (orig_type);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
- || TREE_CODE (orig_type) != ENUMERAL_TYPE
- || TYPE_NAME (orig_type) != get_identifier ("omp_allocator_handle_t"))
+ bool has_modifiers = false;
+ tree orig_type = NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
+ {
+ unsigned int n = 3;
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON)
+ has_modifiers = true;
+ else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COMMA
+ && (c_parser_peek_nth_token_raw (parser, n + 2)->type
+ == CPP_NAME)
+ && (c_parser_peek_nth_token_raw (parser, n + 3)->type
+ == CPP_OPEN_PAREN))
+ {
+ c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
+ const char *q = IDENTIFIER_POINTER (tok->value);
+ n += 4;
+ if ((strcmp (q, "allocator") == 0
+ || strcmp (q, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser,
+ &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON))
+ has_modifiers = true;
+ }
+ }
+ if (has_modifiers)
+ {
+ c_parser_consume_token (parser);
+ matching_parens parens2;;
+ parens2.require_open (parser);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ if (strcmp (p, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ c_token *tok = c_parser_peek_token (parser);
+ const char *q = "";
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ q = IDENTIFIER_POINTER (tok->value);
+ if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
+ {
+ c_parser_error (parser, "expected %<allocator%> or "
+ "%<align%>");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ else if (strcmp (p, q) == 0)
+ {
+ error_at (tok->location, "duplicate %qs modifier", p);
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ c_parser_consume_token (parser);
+ if (!parens2.require_open (parser))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ expr_loc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
+ true);
+ if (strcmp (q, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ }
+ }
+ }
+ if (!has_modifiers)
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ if (allocator
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
+ || TREE_CODE (orig_type) != ENUMERAL_TYPE
+ || (TYPE_NAME (orig_type)
+ != get_identifier ("omp_allocator_handle_t"))))
{
error_at (clause_loc, "%<allocate%> clause allocator expression "
"has type %qT rather than "
@@ -15341,6 +15465,16 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
TREE_TYPE (allocator));
allocator = NULL_TREE;
}
+ if (align
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
+ || !tree_fits_uhwi_p (align)
+ || !integer_pow2p (align)))
+ {
+ error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ align = NULL_TREE;
+ }
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
parens.skip_until_found_close (parser);
@@ -15351,9 +15485,12 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc,
OMP_CLAUSE_ALLOCATE, list);
- if (allocator)
+ if (allocator || align)
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ {
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
parens.skip_until_found_close (parser);
return nl;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index d50d0cb..a046c6b 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -746,7 +746,7 @@ extern tree c_finish_expr_stmt (location_t, tree);
extern tree c_finish_return (location_t, tree, tree);
extern tree c_finish_bc_stmt (location_t, tree, bool);
extern tree c_finish_goto_label (location_t, tree);
-extern tree c_finish_goto_ptr (location_t, tree);
+extern tree c_finish_goto_ptr (location_t, c_expr val);
extern tree c_expr_to_decl (tree, bool *, bool *);
extern tree c_finish_omp_construct (location_t, enum tree_code, tree, tree);
extern tree c_finish_oacc_data (location_t, tree, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 49d1bb0..0aac978 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3940,7 +3940,14 @@ parser_build_binary_op (location_t location, enum tree_code code,
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
warning_at (location, OPT_Waddress,
- "comparison with string literal results in unspecified behavior");
+ "comparison with string literal results in unspecified "
+ "behavior");
+
+ if (warn_array_compare
+ && TREE_CODE_CLASS (code) == tcc_comparison
+ && TREE_CODE (type1) == ARRAY_TYPE
+ && TREE_CODE (type2) == ARRAY_TYPE)
+ do_warn_array_compare (location, code, arg1.value, arg2.value);
if (TREE_OVERFLOW_P (result.value)
&& !TREE_OVERFLOW_P (arg1.value)
@@ -4961,6 +4968,10 @@ lvalue_p (const_tree ref)
case STRING_CST:
return true;
+ case MEM_REF:
+ case TARGET_MEM_REF:
+ /* MEM_REFs can appear from -fgimple parsing or folding, so allow them
+ here as well. */
case INDIRECT_REF:
case ARRAY_REF:
case VAR_DECL:
@@ -10783,10 +10794,19 @@ c_finish_goto_label (location_t loc, tree label)
the GOTO. */
tree
-c_finish_goto_ptr (location_t loc, tree expr)
+c_finish_goto_ptr (location_t loc, c_expr val)
{
+ tree expr = val.value;
tree t;
pedwarn (loc, OPT_Wpedantic, "ISO C forbids %<goto *expr;%>");
+ if (expr != error_mark_node
+ && !POINTER_TYPE_P (TREE_TYPE (expr))
+ && !null_pointer_constant_p (expr))
+ {
+ error_at (val.get_location (),
+ "computed goto must be pointer type");
+ expr = build_zero_cst (ptr_type_node);
+ }
expr = c_fully_fold (expr, false, NULL);
expr = convert (ptr_type_node, expr);
t = build1 (GOTO_EXPR, void_type_node, expr);
@@ -11545,6 +11565,110 @@ build_vec_cmp (tree_code code, tree type,
return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
}
+/* Possibly warn about an address of OP never being NULL in a comparison
+ operation CODE involving null. */
+
+static void
+maybe_warn_for_null_address (location_t loc, tree op, tree_code code)
+{
+ if (!warn_address || warning_suppressed_p (op, OPT_Waddress))
+ return;
+
+ if (TREE_CODE (op) == NOP_EXPR)
+ {
+ /* Allow casts to intptr_t to suppress the warning. */
+ tree type = TREE_TYPE (op);
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ return;
+ op = TREE_OPERAND (op, 0);
+ }
+
+ if (TREE_CODE (op) == POINTER_PLUS_EXPR)
+ {
+ /* Allow a cast to void* to suppress the warning. */
+ tree type = TREE_TYPE (TREE_TYPE (op));
+ if (VOID_TYPE_P (type))
+ return;
+
+ /* Adding any value to a null pointer, including zero, is undefined
+ in C. This includes the expression &p[0] where p is the null
+ pointer, although &p[0] will have been folded to p by this point
+ and so not diagnosed. */
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the pointer operand in %qE must not be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the pointer operand in %qE must not be NULL",
+ op);
+
+ return;
+ }
+
+ if (TREE_CODE (op) != ADDR_EXPR)
+ return;
+
+ op = TREE_OPERAND (op, 0);
+
+ if (TREE_CODE (op) == IMAGPART_EXPR
+ || TREE_CODE (op) == REALPART_EXPR)
+ {
+ /* The address of either complex part may not be null. */
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qE will never be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qE will never be NULL",
+ op);
+ return;
+ }
+
+ /* Set to true in the loop below if OP dereferences is operand.
+ In such a case the ultimate target need not be a decl for
+ the null [in]equality test to be constant. */
+ bool deref = false;
+
+ /* Get the outermost array or object, or member. */
+ while (handled_component_p (op))
+ {
+ if (TREE_CODE (op) == COMPONENT_REF)
+ {
+ /* Get the member (its address is never null). */
+ op = TREE_OPERAND (op, 1);
+ break;
+ }
+
+ /* Get the outer array/object to refer to in the warning. */
+ op = TREE_OPERAND (op, 0);
+ deref = true;
+ }
+
+ if ((!deref && !decl_with_nonnull_addr_p (op))
+ || from_macro_expansion_at (loc))
+ return;
+
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qE will never be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qE will never be NULL",
+ op);
+
+ if (DECL_P (op))
+ inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
+}
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the operator's location.
@@ -12180,44 +12304,12 @@ build_binary_op (location_t location, enum tree_code code,
short_compare = 1;
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
- if (TREE_CODE (op0) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))
- && !from_macro_expansion_at (location))
- {
- if (code == EQ_EXPR)
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<false%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op0, 0));
- else
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<true%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op0, 0));
- }
+ maybe_warn_for_null_address (location, op0, code);
result_type = type0;
}
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
- if (TREE_CODE (op1) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0))
- && !from_macro_expansion_at (location))
- {
- if (code == EQ_EXPR)
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<false%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op1, 0));
- else
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<true%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op1, 0));
- }
+ maybe_warn_for_null_address (location, op1, code);
result_type = type1;
}
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
@@ -12724,7 +12816,9 @@ build_binary_op (location_t location, enum tree_code code,
}
if (sanitize_flags_p ((SANITIZE_SHIFT
- | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ | SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))
&& current_function_decl != NULL_TREE
&& (doing_div_or_mod || doing_shift)
&& !require_constant_value)
@@ -12735,7 +12829,8 @@ build_binary_op (location_t location, enum tree_code code,
op0 = c_fully_fold (op0, false, NULL);
op1 = c_fully_fold (op1, false, NULL);
if (doing_div_or_mod && (sanitize_flags_p ((SANITIZE_DIVIDE
- | SANITIZE_FLOAT_DIVIDE))))
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))))
instrument_expr = ubsan_instrument_division (location, op0, op1);
else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT))
instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index c8d9db6..c43ee38 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1622,16 +1622,20 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
tree val = c_parser_gimple_postfix_expression (parser).value;
if (! val
|| val == error_mark_node
- || (!CONSTANT_CLASS_P (val)
- && !(addr_p
- && (TREE_CODE (val) == STRING_CST
- || DECL_P (val)))))
+ || (!CONSTANT_CLASS_P (val) && !addr_p))
{
c_parser_error (parser, "invalid _Literal");
return expr;
}
if (addr_p)
- val = build1 (ADDR_EXPR, type, val);
+ {
+ val = build1 (ADDR_EXPR, type, val);
+ if (!is_gimple_invariant_address (val))
+ {
+ c_parser_error (parser, "invalid _Literal");
+ return expr;
+ }
+ }
if (neg_p)
{
val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val);