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 | |
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')
-rw-r--r-- | gcc/c/ChangeLog | 44 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 169 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 2 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 171 | ||||
-rw-r--r-- | gcc/c/gimple-parser.c | 14 |
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); |