From 85872a69ee1b123557c7c352d45ef608e70b20fb Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 5 Oct 2022 00:17:25 +0000 Subject: Daily bump. --- gcc/c/ChangeLog | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'gcc/c') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index f5c9a59..48eb23e 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,30 @@ +2022-10-04 Jakub Jelinek + + * c-lang.h (struct c_omp_declare_target_attr): New type. + (current_omp_declare_target_attribute): Change type from + int to vec *. + * c-parser.cc (c_parser_translation_unit): Adjust for that change. + If last pushed directive was begin declare target, use different + wording and simplify format strings for easier translations. + (c_parser_omp_clause_device_type): Uncomment + check_no_duplicate_clause call. + (c_parser_omp_declare_target): Adjust for the + current_omp_declare_target_attribute type change, push { -1 }. + Use error_at rather than warning_at for declare target with + only device_type clauses. + (OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Define. + (c_parser_omp_begin): Add begin declare target support. + (c_parser_omp_end): Adjust for the + current_omp_declare_target_attribute type change, adjust + diagnostics wording and simplify format strings for easier + translations. + * c-decl.cc (current_omp_declare_target_attribute): Change type from + int to vec *. + (c_decl_attributes): Adjust for the + current_omp_declare_target_attribute type change. If device_type + was present on begin declare target, add "omp declare target host" + and/or "omp declare target nohost" attributes. + 2022-09-29 Joseph Myers * c-decl.cc (handle_std_noreturn_attribute): New function. -- cgit v1.1 From 08b51baddc53d64aa4c5e7a81ef3c4bf320293be Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 6 Oct 2022 08:56:48 +0200 Subject: c++, c: Implement C++23 P1774R8 - Portable assumptions [PR106654] The following patch implements C++23 P1774R8 - Portable assumptions paper, by introducing support for [[assume (cond)]]; attribute for C++. In addition to that the patch adds [[gnu::assume (cond)]]; and __attribute__((assume (cond))); support to both C and C++. As described in C++23, the attribute argument is conditional-expression rather than the usual assignment-expression for attribute arguments, the condition is contextually converted to bool (for C truthvalue conversion is done on it) and is never evaluated at runtime. For C++ constant expression evaluation, I only check the simplest conditions for undefined behavior, because otherwise I'd need to undo changes to *ctx->global which happened during the evaluation (but I believe the spec allows that and we can further improve later). The patch uses a new internal function, .ASSUME, to hold the condition in the FEs. At gimplification time, if the condition is simple/without side-effects, it is gimplified as if (cond) ; else __builtin_unreachable (); and otherwise for now dropped on the floor. The intent is to incrementally outline the conditions into separate artificial functions and use .ASSUME further to tell the ranger and perhaps other optimization passes about the assumptions, as detailed in the PR. When implementing it, I found that assume entry hasn't been added to https://eel.is/c++draft/cpp.cond#6 Jonathan said he'll file a NB comment about it, this patch assumes it has been added into the table as 202207L when the paper has been voted in. With the attributes for both C/C++, I'd say we don't need to add __builtin_assume with similar purpose, especially when __builtin_assume in LLVM is just weird. It is strange for side-effects in function call's argument not to be evaluated, and LLVM in that case (annoyingly) warns and ignores the side-effects (but doesn't do then anything with it), if there are no side-effects, it will work like our if (!cond) __builtin_unreachable (); 2022-10-06 Jakub Jelinek PR c++/106654 gcc/ * internal-fn.def (ASSUME): New internal function. * internal-fn.h (expand_ASSUME): Declare. * internal-fn.cc (expand_ASSUME): Define. * gimplify.cc (gimplify_call_expr): Gimplify IFN_ASSUME. * fold-const.h (simple_condition_p): Declare. * fold-const.cc (simple_operand_p_2): Rename to ... (simple_condition_p): ... this. Remove forward declaration. No longer static. Adjust function comment and fix a typo in it. Adjust recursive call. (simple_operand_p): Adjust function comment. (fold_truth_andor): Adjust simple_operand_p_2 callers to call simple_condition_p. * doc/extend.texi: Document assume attribute. Move fallthrough attribute example to its section. gcc/c-family/ * c-attribs.cc (handle_assume_attribute): New function. (c_common_attribute_table): Add entry for assume attribute. * c-lex.cc (c_common_has_attribute): Handle __have_cpp_attribute (assume). gcc/c/ * c-parser.cc (handle_assume_attribute): New function. (c_parser_declaration_or_fndef): Handle assume attribute. (c_parser_attribute_arguments): Add assume_attr argument, if true, parse first argument as conditional expression. (c_parser_gnu_attribute, c_parser_std_attribute): Adjust c_parser_attribute_arguments callers. (c_parser_statement_after_labels) : Handle assume attribute. gcc/cp/ * cp-tree.h (process_stmt_assume_attribute): Implement C++23 P1774R8 - Portable assumptions. Declare. (diagnose_failing_condition): Declare. (find_failing_clause): Likewise. * parser.cc (assume_attr): New enumerator. (cp_parser_parenthesized_expression_list): Handle assume_attr. Remove identifier variable, for id_attr push the identifier into expression_list right away instead of inserting it before all the others at the end. (cp_parser_conditional_expression): New function. (cp_parser_constant_expression): Use it. (cp_parser_statement): Handle assume attribute. (cp_parser_expression_statement): Likewise. (cp_parser_gnu_attribute_list): Use assume_attr for assume attribute. (cp_parser_std_attribute): Likewise. Handle standard assume attribute like gnu::assume. * cp-gimplify.cc (process_stmt_assume_attribute): New function. * constexpr.cc: Include fold-const.h. (find_failing_clause_r, find_failing_clause): New functions, moved from semantics.cc with ctx argument added and if non-NULL, call cxx_eval_constant_expression rather than fold_non_dependent_expr. (cxx_eval_internal_function): Handle IFN_ASSUME. (potential_constant_expression_1): Likewise. * pt.cc (tsubst_copy_and_build): Likewise. * semantics.cc (diagnose_failing_condition): New function. (find_failing_clause_r, find_failing_clause): Moved to constexpr.cc. (finish_static_assert): Use it. Add auto_diagnostic_group. gcc/testsuite/ * gcc.dg/attr-assume-1.c: New test. * gcc.dg/attr-assume-2.c: New test. * gcc.dg/attr-assume-3.c: New test. * g++.dg/cpp2a/feat-cxx2a.C: Add colon to C++20 features comment, add C++20 attributes comment and move C++20 new features after the attributes before them. * g++.dg/cpp23/feat-cxx2b.C: Likewise. Test __has_cpp_attribute(assume). * g++.dg/cpp23/attr-assume1.C: New test. * g++.dg/cpp23/attr-assume2.C: New test. * g++.dg/cpp23/attr-assume3.C: New test. * g++.dg/cpp23/attr-assume4.C: New test. --- gcc/c/c-parser.cc | 113 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 104 insertions(+), 9 deletions(-) (limited to 'gcc/c') diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index f6a94ba..9b76637 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1823,6 +1823,46 @@ add_debug_begin_stmt (location_t loc) add_stmt (stmt); } +/* Helper function for c_parser_declaration_or_fndef and + Handle assume attribute(s). */ + +static tree +handle_assume_attribute (location_t here, tree attrs, bool nested) +{ + if (nested) + for (tree attr = lookup_attribute ("gnu", "assume", attrs); attr; + attr = lookup_attribute ("gnu", "assume", TREE_CHAIN (attr))) + { + tree args = TREE_VALUE (attr); + int nargs = list_length (args); + if (nargs != 1) + { + error_at (here, "wrong number of arguments specified " + "for %qE attribute", + get_attribute_name (attr)); + inform (here, "expected %i, found %i", 1, nargs); + } + else + { + tree arg = TREE_VALUE (args); + arg = c_objc_common_truthvalue_conversion (here, arg); + arg = c_fully_fold (arg, false, NULL); + if (arg != error_mark_node) + { + tree fn = build_call_expr_internal_loc (here, IFN_ASSUME, + void_type_node, 1, + arg); + add_stmt (fn); + } + } + } + else + pedwarn (here, OPT_Wattributes, + "% attribute at top level"); + + return remove_attribute ("gnu", "assume", attrs); +} + /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition is accepted; otherwise (old-style parameter declarations) only other @@ -2037,6 +2077,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool auto_type_p = specs->typespec_word == cts_auto_type; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { + bool handled_assume = false; + if (specs->typespec_kind == ctsk_none + && lookup_attribute ("gnu", "assume", specs->attrs)) + { + handled_assume = true; + specs->attrs + = handle_assume_attribute (here, specs->attrs, nested); + } if (auto_type_p) error_at (here, "%<__auto_type%> in empty declaration"); else if (specs->typespec_kind == ctsk_none @@ -2054,13 +2102,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, pedwarn (here, OPT_Wattributes, "% attribute at top level"); } - else if (empty_ok && !(have_attrs - && specs->non_std_attrs_seen_p)) + else if (empty_ok + && !(have_attrs && specs->non_std_attrs_seen_p) + && !handled_assume) shadow_tag (specs); else { shadow_tag_warned (specs, 1); - pedwarn (here, 0, "empty declaration"); + if (!handled_assume) + pedwarn (here, 0, "empty declaration"); } c_parser_consume_token (parser); if (oacc_routine_data) @@ -2160,6 +2210,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, else if (attribute_fallthrough_p (specs->attrs)) warning_at (here, OPT_Wattributes, "% attribute not followed by %<;%>"); + else if (lookup_attribute ("gnu", "assume", specs->attrs)) + warning_at (here, OPT_Wattributes, + "% attribute not followed by %<;%>"); pending_xref_error (); prefix_attrs = specs->attrs; @@ -4598,7 +4651,8 @@ c_parser_gnu_attribute_any_word (c_parser *parser) static tree c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, - bool require_string, bool allow_empty_args) + bool require_string, bool assume_attr, + bool allow_empty_args) { vec *expr_list; tree attr_args; @@ -4617,6 +4671,7 @@ c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, == CPP_CLOSE_PAREN)) && (takes_identifier || (c_dialect_objc () + && !assume_attr && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))) { @@ -4653,6 +4708,23 @@ c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, tree string = c_parser_string_literal (parser, false, true).value; attr_args = build_tree_list (NULL_TREE, string); } + else if (assume_attr) + { + tree cond + = c_parser_conditional_expression (parser, NULL, NULL_TREE).value; + if (!c_parser_next_token_is (parser, CPP_COMMA)) + attr_args = build_tree_list (NULL_TREE, cond); + else + { + tree tree_list; + c_parser_consume_token (parser); + expr_list = c_parser_expr_list (parser, false, true, + NULL, NULL, NULL, NULL); + tree_list = build_tree_list_vec (expr_list); + attr_args = tree_cons (NULL_TREE, cond, tree_list); + release_tree_vector (expr_list); + } + } else { expr_list = c_parser_expr_list (parser, false, true, @@ -4736,7 +4808,9 @@ c_parser_gnu_attribute (c_parser *parser, tree attrs, tree attr_args = c_parser_attribute_arguments (parser, attribute_takes_identifier_p (attr_name), - false, true); + false, + is_attribute_p ("assume", attr_name), + true); attr = build_tree_list (attr_name, attr_args); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) @@ -4982,9 +5056,13 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) = (ns == NULL_TREE && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0 || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0)); + bool assume_attr + = (ns != NULL_TREE + && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0 + && strcmp (IDENTIFIER_POINTER (name), "assume") == 0); TREE_VALUE (attribute) = c_parser_attribute_arguments (parser, takes_identifier, - require_string, false); + require_string, assume_attr, false); } else c_parser_balanced_token_sequence (parser); @@ -6264,8 +6342,21 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, break; case RID_ATTRIBUTE: { - /* Allow '__attribute__((fallthrough));'. */ + /* Allow '__attribute__((fallthrough));' or + '__attribute__((assume(cond)));'. */ tree attrs = c_parser_gnu_attributes (parser); + bool has_assume = lookup_attribute ("assume", attrs); + if (has_assume) + { + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + attrs = handle_assume_attribute (loc, attrs, true); + else + { + warning_at (loc, OPT_Wattributes, + "% attribute not followed by %<;%>"); + has_assume = false; + } + } if (attribute_fallthrough_p (attrs)) { if (c_parser_next_token_is (parser, CPP_SEMICOLON)) @@ -6282,9 +6373,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, "% attribute not followed " "by %<;%>"); } + else if (has_assume) + /* Eat the ';'. */ + c_parser_consume_token (parser); else if (attrs != NULL_TREE) - warning_at (loc, OPT_Wattributes, "only attribute %" - " can be applied to a null statement"); + warning_at (loc, OPT_Wattributes, + "only attribute % or % can " + "be applied to a null statement"); break; } default: -- cgit v1.1 From 847f5addc4d07a2f3b95f5daa50ab4a64dfd957d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 6 Oct 2022 10:39:41 +0200 Subject: openmp: Map holds clause to IFN_ASSUME for C/C++ Now that [[assume (cond)]] support is in, this simple patch makes #pragma omp assume holds(cond) use it. 2022-10-06 Jakub Jelinek * c-parser.cc (c_parser_omp_assumption_clauses): Emit IFN_ASSUME call for holds clause on assume construct. * parser.cc (cp_parser_omp_assumption_clauses): Emit IFN_ASSUME call for holds clause on assume construct. * c-c++-common/gomp/assume-4.c: New test. --- gcc/c/c-parser.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'gcc/c') diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 9b76637..67b919c 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -23571,10 +23571,12 @@ c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume) tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value; t = c_objc_common_truthvalue_conversion (eloc, t); t = c_fully_fold (t, false, NULL); - if (is_assume) + if (is_assume && t != error_mark_node) { - /* FIXME: Emit .ASSUME (t) call here. */ - (void) t; + tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME, + void_type_node, 1, + t); + add_stmt (fn); } parens.skip_until_found_close (parser); } -- cgit v1.1 From fa258f6894801aef6785f0327594dc803da63fbd Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 6 Oct 2022 14:26:21 +0000 Subject: c: C2x typeof C2x adds typeof as a standard feature. In general this follows existing GNU C semantics very closely, but there are various ways in which the implementation involves more than simply enabling the keyword for C2x: * As well as typeof, there is a typeof_unqual variant, which removes all qualifiers and _Atomic from the resulting type (whereas typeof preserves qualifiers and _Atomic on qualified or atomic (lvalue or type name) operands). * The typeof keyword is disabled by -fno-asm, so enabling it for C2x needs to be implemented in a way that preserves the disabling by -fno-asm for older standard versions (which having -fno-asm having no effect on it in C2x mode). This is done via adding a new D_EXT11 mask (which is also where the C++ front-end change comes from, to handle D_EXT11 appropriately there for -fno-asm and -fno-gnu-keywords). * GNU typeof treats the noreturn property of a function (as specified in standard C with _Noreturn or [[noreturn]]) as being part of the type of a pointer to function, but it is not part of the type in standard terms. Thus a special case is needed in the typeof implementation, just like in the _Generic implementation, to avoid treating it as a type for standard typeof. It seems plausible this is being used when copying the type of one object to another using typeof, so the existing semantics are preserved for __typeof__, and for typeof in pre-C2x modes, while typeof for C2x or later has the standard semantics. * It turns out that, even after Martin Uecker's changes in this area, there were still cases where rvalues could wrongly have a qualified or atomic type in GCC. This applied to ++ and -- increment and decrement expressions, and also to calls to functions returning an atomic type. (For the latter, the working draft doesn't actually explicitly exclude the function call expression having an atomic type, but given all the changes that have gone into C17 and C2x to avoid rvalues ever having qualified types, and given that lvalue-to-rvalue conversion removes both qualifiers and _Atomic, it seems unlikely that this (or casts, where GCC already removes _Atomic) is actually intended as a route to allow an _Atomic-qualified rvalue; I've noted this to raise as an NB comment on the CD ballot.) Bootstrapped with no regressions for x86_64-pc-linux-gnu. OK to commit (C+ gcc/ * doc/invoke.texi (-fno-asm): Update description of effects on typeof keyword. gcc/c-family/ * c-common.cc (c_common_reswords): Mark typeof as D_EXT11. Add typeof_unqual. * c-common.h (enum rid): Add RID_TYPEOF_UNQUAL. (D_EXT11): New macro. Values of subsequent macros updated. gcc/c/ * c-parser.cc (c_parse_init): Add D_EXT11 to mask if flag_no_asm and not C2x. (c_keyword_starts_typename, c_token_starts_declspecs) (c_parser_declspecs, c_parser_objc_selector): Handle RID_TYPEOF_UNQUAL. (c_parser_typeof_specifier): Handle RID_TYPEOF_UNQUAL. Distinguish typeof for C2x from __typeof__ for all standard versions and typeof before C2x. * c-typeck.cc (build_function_call_vec): Use unqualified version of non-void return type. (build_unary_op): Use unqualified type for increment and decrement. gcc/cp/ * lex.cc (init_reswords): Handle D_EXT11. gcc/testsuite/ * gcc.dg/c11-typeof-1.c, gcc.dg/c2x-typeof-1.c, gcc.dg/c2x-typeof-2.c, gcc.dg/c2x-typeof-3.c, gcc.dg/gnu11-typeof-1.c, gcc.dg/gnu11-typeof-2.c, gcc.dg/gnu2x-typeof-1.c: New tests. --- gcc/c/c-parser.cc | 46 +++++++++++++++++++++++++++++++++++++++++++--- gcc/c/c-typeck.cc | 15 ++++++++++----- 2 files changed, 53 insertions(+), 8 deletions(-) (limited to 'gcc/c') diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 67b919c..89e0587 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -127,6 +127,8 @@ c_parse_init (void) mask |= D_ASM | D_EXT; if (!flag_isoc99) mask |= D_EXT89; + if (!flag_isoc2x) + mask |= D_EXT11; } if (!c_dialect_objc ()) mask |= D_OBJC | D_CXX_OBJC; @@ -580,6 +582,7 @@ c_keyword_starts_typename (enum rid keyword) case RID_STRUCT: case RID_UNION: case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: case RID_CONST: case RID_ATOMIC: case RID_VOLATILE: @@ -757,6 +760,7 @@ c_token_starts_declspecs (c_token *token) case RID_STRUCT: case RID_UNION: case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: case RID_CONST: case RID_VOLATILE: case RID_RESTRICT: @@ -3081,6 +3085,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, declspecs_add_type (loc, specs, t); break; case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: /* ??? The old parser rejected typeof after other type specifiers, but is a syntax error the best way of handling this? */ @@ -3768,22 +3773,38 @@ c_parser_struct_declaration (c_parser *parser) return decls; } -/* Parse a typeof specifier (a GNU extension). +/* Parse a typeof specifier (a GNU extension adopted in C2X). typeof-specifier: typeof ( expression ) typeof ( type-name ) + typeof_unqual ( expression ) + typeof_unqual ( type-name ) */ static struct c_typespec c_parser_typeof_specifier (c_parser *parser) { + bool is_unqual; + bool is_std; struct c_typespec ret; ret.kind = ctsk_typeof; ret.spec = error_mark_node; ret.expr = NULL_TREE; ret.expr_const_operands = true; - gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF)); + if (c_parser_next_token_is_keyword (parser, RID_TYPEOF)) + { + is_unqual = false; + tree spelling = c_parser_peek_token (parser)->value; + is_std = (flag_isoc2x + && strcmp (IDENTIFIER_POINTER (spelling), "typeof") == 0); + } + else + { + gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL)); + is_unqual = true; + is_std = true; + } c_parser_consume_token (parser); c_inhibit_evaluation_warnings++; in_typeof++; @@ -3825,6 +3846,24 @@ c_parser_typeof_specifier (c_parser *parser) pop_maybe_used (was_vm); } parens.skip_until_found_close (parser); + if (ret.spec != error_mark_node) + { + if (is_unqual && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED) + ret.spec = TYPE_MAIN_VARIANT (ret.spec); + if (is_std) + { + /* In ISO C terms, _Noreturn is not part of the type of + expressions such as &abort, but in GCC it is represented + internally as a type qualifier. */ + if (TREE_CODE (ret.spec) == FUNCTION_TYPE + && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED) + ret.spec = TYPE_MAIN_VARIANT (ret.spec); + else if (FUNCTION_POINTER_TYPE_P (ret.spec) + && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED) + ret.spec + = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec))); + } + } return ret; } @@ -11961,7 +12000,7 @@ c_parser_objc_synchronized_statement (c_parser *parser) identifier one of enum struct union if else while do for switch case default - break continue return goto asm sizeof typeof __alignof + break continue return goto asm sizeof typeof typeof_unqual __alignof unsigned long const short volatile signed restrict _Complex in out inout bycopy byref oneway int char float double void _Bool _Atomic @@ -12001,6 +12040,7 @@ c_parser_objc_selector (c_parser *parser) case RID_ASM: case RID_SIZEOF: case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: case RID_ALIGNOF: case RID_UNSIGNED: case RID_LONG: diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index ac242b5..f919068 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -3187,6 +3187,7 @@ build_function_call_vec (location_t loc, vec arg_loc, /* fntype now gets the type of function pointed to. */ fntype = TREE_TYPE (fntype); + tree return_type = TREE_TYPE (fntype); /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ @@ -3203,8 +3204,6 @@ build_function_call_vec (location_t loc, vec arg_loc, && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL && !comptypes (fntype, TREE_TYPE (tem))) { - tree return_type = TREE_TYPE (fntype); - /* This situation leads to run-time undefined behavior. We can't, therefore, simply error unless we can prove that all possible executions of the program must execute the code. */ @@ -3229,22 +3228,25 @@ build_function_call_vec (location_t loc, vec arg_loc, bool warned_p = check_function_arguments (loc, fundecl, fntype, nargs, argarray, &arg_loc); + if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED + && !VOID_TYPE_P (return_type)) + return_type = c_build_qualified_type (return_type, TYPE_UNQUALIFIED); if (name != NULL_TREE && startswith (IDENTIFIER_POINTER (name), "__builtin_")) { if (require_constant_value) result - = fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype), + = fold_build_call_array_initializer_loc (loc, return_type, function, nargs, argarray); else - result = fold_build_call_array_loc (loc, TREE_TYPE (fntype), + result = fold_build_call_array_loc (loc, return_type, function, nargs, argarray); if (TREE_CODE (result) == NOP_EXPR && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST) STRIP_TYPE_NOPS (result); } else - result = build_call_array_loc (loc, TREE_TYPE (fntype), + result = build_call_array_loc (loc, return_type, function, nargs, argarray); /* If -Wnonnull warning has been diagnosed, avoid diagnosing it again later. */ @@ -4831,6 +4833,9 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, else val = build2 (code, TREE_TYPE (arg), arg, inc); TREE_SIDE_EFFECTS (val) = 1; + if (TYPE_QUALS (TREE_TYPE (val)) != TYPE_UNQUALIFIED) + TREE_TYPE (val) = c_build_qualified_type (TREE_TYPE (val), + TYPE_UNQUALIFIED); ret = val; goto return_build_unary_op; } -- cgit v1.1 From 629d04d35d819bdc26c30d215bc4ea66a74af15b Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 7 Oct 2022 00:17:52 +0000 Subject: Daily bump. --- gcc/c/ChangeLog | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'gcc/c') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 48eb23e..325b1f8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,35 @@ +2022-10-06 Joseph Myers + + * c-parser.cc (c_parse_init): Add D_EXT11 to mask if flag_no_asm + and not C2x. + (c_keyword_starts_typename, c_token_starts_declspecs) + (c_parser_declspecs, c_parser_objc_selector): Handle + RID_TYPEOF_UNQUAL. + (c_parser_typeof_specifier): Handle RID_TYPEOF_UNQUAL. + Distinguish typeof for C2x from __typeof__ for all standard + versions and typeof before C2x. + * c-typeck.cc (build_function_call_vec): Use unqualified version + of non-void return type. + (build_unary_op): Use unqualified type for increment and + decrement. + +2022-10-06 Jakub Jelinek + + * c-parser.cc (c_parser_omp_assumption_clauses): Emit IFN_ASSUME + call for holds clause on assume construct. + +2022-10-06 Jakub Jelinek + + PR c++/106654 + * c-parser.cc (handle_assume_attribute): New function. + (c_parser_declaration_or_fndef): Handle assume attribute. + (c_parser_attribute_arguments): Add assume_attr argument, + if true, parse first argument as conditional expression. + (c_parser_gnu_attribute, c_parser_std_attribute): Adjust + c_parser_attribute_arguments callers. + (c_parser_statement_after_labels) : Handle + assume attribute. + 2022-10-04 Jakub Jelinek * c-lang.h (struct c_omp_declare_target_attr): New type. -- cgit v1.1 From 1879e48f3d8595bc9e7f583bbd12df3c6f5c42dc Mon Sep 17 00:00:00 2001 From: Qing Zhao Date: Fri, 7 Oct 2022 14:58:20 +0000 Subject: Add a new option -fstrict-flex-arrays[=n] and new attribute strict_flex_array Add the following new option -fstrict-flex-arrays[=n] and a corresponding attribute strict_flex_array to GCC: '-fstrict-flex-arrays' Control when to treat the trailing array of a structure as a flexible array member for the purpose of accessing the elements of such an array. The positive form is equivalent to '-fstrict-flex-arrays=3', which is the strictest. A trailing array is treated as a flexible array member only when it declared as a flexible array member per C99 standard onwards. The negative form is equivalent to '-fstrict-flex-arrays=0', which is the least strict. All trailing arrays of structures are treated as flexible array members. '-fstrict-flex-arrays=LEVEL' Control when to treat the trailing array of a structure as a flexible array member for the purpose of accessing the elements of such an array. The value of LEVEL controls the level of strictness The possible values of LEVEL are the same as for the 'strict_flex_array' attribute (*note Variable Attributes::). You can control this behavior for a specific trailing array field of a structure by using the variable attribute 'strict_flex_array' attribute (*note Variable Attributes::). 'strict_flex_array (LEVEL)' The 'strict_flex_array' attribute should be attached to the trailing array field of a structure. It controls when to treat the trailing array field of a structure as a flexible array member for the purposes of accessing the elements of such an array. LEVEL must be an integer betwen 0 to 3. LEVEL=0 is the least strict level, all trailing arrays of structures are treated as flexible array members. LEVEL=3 is the strictest level, only when the trailing array is declared as a flexible array member per C99 standard onwards ('[]'), it is treated as a flexible array member. There are two more levels in between 0 and 3, which are provided to support older codes that use GCC zero-length array extension ('[0]') or one-element array as flexible array members('[1]'): When LEVEL is 1, the trailing array is treated as a flexible array member when it is declared as either '[]', '[0]', or '[1]'; When LEVEL is 2, the trailing array is treated as a flexible array member when it is declared as either '[]', or '[0]'. This attribute can be used with or without the '-fstrict-flex-arrays'. When both the attribute and the option present at the same time, the level of the strictness for the specific trailing array field is determined by the attribute. gcc/c-family/ChangeLog: * c-attribs.cc (handle_strict_flex_array_attribute): New function. (c_common_attribute_table): New item for strict_flex_array. * c.opt: (fstrict-flex-arrays): New option. (fstrict-flex-arrays=): New option. gcc/c/ChangeLog: * c-decl.cc (flexible_array_member_type_p): New function. (one_element_array_type_p): Likewise. (zero_length_array_type_p): Likewise. (add_flexible_array_elts_to_size): Call new utility routine flexible_array_member_type_p. (is_flexible_array_member_p): New function. (finish_struct): Set the new DECL_NOT_FLEXARRAY flag. gcc/cp/ChangeLog: * module.cc (trees_out::core_bools): Stream out new bit decl_not_flexarray. (trees_in::core_bools): Stream in new bit decl_not_flexarray. gcc/ChangeLog: * doc/extend.texi: Document strict_flex_array attribute. * doc/invoke.texi: Document -fstrict-flex-arrays[=n] option. * print-tree.cc (print_node): Print new bit decl_not_flexarray. * tree-core.h (struct tree_decl_common): New bit field decl_not_flexarray. * tree-streamer-in.cc (unpack_ts_decl_common_value_fields): Stream in new bit decl_not_flexarray. * tree-streamer-out.cc (pack_ts_decl_common_value_fields): Stream out new bit decl_not_flexarray. * tree.cc (array_at_struct_end_p): Update it with the new bit field decl_not_flexarray. * tree.h (DECL_NOT_FLEXARRAY): New flag. gcc/testsuite/ChangeLog: * g++.dg/strict-flex-array-1.C: New test. * gcc.dg/strict-flex-array-1.c: New test. --- gcc/c/c-decl.cc | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 9 deletions(-) (limited to 'gcc/c') diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index ffa63dc..193e268 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5034,6 +5034,41 @@ set_array_declarator_inner (struct c_declarator *decl, return decl; } +/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]". */ +static bool +flexible_array_member_type_p (const_tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) == NULL_TREE + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + return true; + + return false; +} + +/* Determine whether TYPE is a one-element array type "[1]". */ +static bool +one_element_array_type_p (const_tree type) +{ + if (TREE_CODE (type) != ARRAY_TYPE) + return false; + return integer_zerop (array_type_nelts (type)); +} + +/* Determine whether TYPE is a zero-length array type "[0]". */ +static bool +zero_length_array_type_p (const_tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE) + if (tree type_size = TYPE_SIZE_UNIT (type)) + if ((integer_zerop (type_size)) + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + return true; + return false; +} + /* INIT is a constructor that forms DECL's initializer. If the final element initializes a flexible array field, add the size of that initializer to DECL's size. */ @@ -5048,10 +5083,7 @@ add_flexible_array_elts_to_size (tree decl, tree init) elt = CONSTRUCTOR_ELTS (init)->last ().value; type = TREE_TYPE (elt); - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_SIZE (type) == NULL_TREE - && TYPE_DOMAIN (type) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + if (flexible_array_member_type_p (type)) { complete_array_type (&type, elt, false); DECL_SIZE (decl) @@ -8755,6 +8787,81 @@ finish_incomplete_vars (tree incomplete_vars, bool toplevel) } } + +/* Determine whether the FIELD_DECL X is a flexible array member according to + the following info: + A. whether the FIELD_DECL X is the last field of the DECL_CONTEXT; + B. whether the FIELD_DECL is an array that is declared as "[]", "[0]", + or "[1]"; + C. flag_strict_flex_arrays; + D. the attribute strict_flex_array that is attached to the field + if presenting. + Return TRUE when it's a flexible array member, FALSE otherwise. */ + +static bool +is_flexible_array_member_p (bool is_last_field, + tree x) +{ + /* If not the last field, return false. */ + if (!is_last_field) + return false; + + /* If not an array field, return false. */ + if (TREE_CODE (TREE_TYPE (x)) != ARRAY_TYPE) + return false; + + bool is_zero_length_array = zero_length_array_type_p (TREE_TYPE (x)); + bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x)); + bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x)); + + unsigned int strict_flex_array_level = flag_strict_flex_arrays; + + tree attr_strict_flex_array = lookup_attribute ("strict_flex_array", + DECL_ATTRIBUTES (x)); + /* If there is a strict_flex_array attribute attached to the field, + override the flag_strict_flex_arrays. */ + if (attr_strict_flex_array) + { + /* Get the value of the level first from the attribute. */ + unsigned HOST_WIDE_INT attr_strict_flex_array_level = 0; + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); + gcc_assert (tree_fits_uhwi_p (attr_strict_flex_array)); + attr_strict_flex_array_level = tree_to_uhwi (attr_strict_flex_array); + + /* The attribute has higher priority than flag_struct_flex_array. */ + strict_flex_array_level = attr_strict_flex_array_level; + } + + switch (strict_flex_array_level) + { + case 0: + /* Default, all trailing arrays are flexible array members. */ + return true; + case 1: + /* Level 1: all "[1]", "[0]", and "[]" are flexible array members. */ + if (is_one_element_array) + return true; + /* FALLTHROUGH. */ + case 2: + /* Level 2: all "[0]", and "[]" are flexible array members. */ + if (is_zero_length_array) + return true; + /* FALLTHROUGH. */ + case 3: + /* Level 3: Only "[]" are flexible array members. */ + if (is_flexible_array) + return true; + break; + default: + gcc_unreachable (); + } + return false; +} + + /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. LOC is the location of the RECORD_TYPE or UNION_TYPE's definition. FIELDLIST is a chain of FIELD_DECL nodes for the fields. @@ -8816,6 +8923,11 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, bool saw_named_field = false; for (x = fieldlist; x; x = DECL_CHAIN (x)) { + /* Whether this field is the last field of the structure or union. + for UNION, any field is the last field of it. */ + bool is_last_field = (DECL_CHAIN (x) == NULL_TREE) + || (TREE_CODE (t) == UNION_TYPE); + if (TREE_TYPE (x) == error_mark_node) continue; @@ -8854,10 +8966,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, DECL_PACKED (x) = 1; /* Detect flexible array member in an invalid context. */ - if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE - && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE - && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE) + if (flexible_array_member_type_p (TREE_TYPE (x))) { if (TREE_CODE (t) == UNION_TYPE) { @@ -8865,7 +8974,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, "flexible array member in union"); TREE_TYPE (x) = error_mark_node; } - else if (DECL_CHAIN (x) != NULL_TREE) + else if (!is_last_field) { error_at (DECL_SOURCE_LOCATION (x), "flexible array member not at end of struct"); @@ -8885,6 +8994,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic, "invalid use of structure with flexible array member"); + /* Set DECL_NOT_FLEXARRAY flag for FIELD_DECL x. */ + DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x); + if (DECL_NAME (x) || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))) saw_named_field = true; -- cgit v1.1 From 9ff6c33e2ec0d75958d3f19089519034e8f96a30 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 8 Oct 2022 00:17:29 +0000 Subject: Daily bump. --- gcc/c/ChangeLog | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'gcc/c') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 325b1f8..a25e1b4 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,13 @@ +2022-10-07 Qing Zhao + + * c-decl.cc (flexible_array_member_type_p): New function. + (one_element_array_type_p): Likewise. + (zero_length_array_type_p): Likewise. + (add_flexible_array_elts_to_size): Call new utility + routine flexible_array_member_type_p. + (is_flexible_array_member_p): New function. + (finish_struct): Set the new DECL_NOT_FLEXARRAY flag. + 2022-10-06 Joseph Myers * c-parser.cc (c_parse_init): Add D_EXT11 to mask if flag_no_asm -- cgit v1.1