aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog427
-rw-r--r--gcc/c/c-aux-info.c4
-rw-r--r--gcc/c/c-decl.c114
-rw-r--r--gcc/c/c-fold.c8
-rw-r--r--gcc/c/c-objc-common.c21
-rw-r--r--gcc/c/c-parser.c1432
-rw-r--r--gcc/c/c-tree.h9
-rw-r--r--gcc/c/c-typeck.c614
-rw-r--r--gcc/c/gimple-parser.c24
9 files changed, 2190 insertions, 463 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index e1da067..28fe7bc 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,430 @@
+2021-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_conditional_expression): If omp_atomic_lhs and
+ cond.value is >, < or == with omp_atomic_lhs as one of the operands,
+ don't call build_conditional_expr, instead build a COND_EXPR directly.
+ (c_parser_binary_expression): Avoid calling parser_build_binary_op
+ if omp_atomic_lhs even in more cases for >, < or ==.
+ (c_parser_omp_atomic): Update function comment for OpenMP 5.1 atomics,
+ parse OpenMP 5.1 atomics and fail, compare and weak clauses, allow
+ acq_rel on atomic read/write and acq_rel/acquire clauses on update.
+ * c-typeck.c (build_binary_op): For flag_openmp only handle
+ MIN_EXPR/MAX_EXPR.
+
+2021-09-07 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_flush): Parse 'seq_cst' clause on 'flush'
+ directive.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-decl.c (enum deprecated_states): Add unavailable state.
+ (merge_decls): Copy unavailability.
+ (quals_from_declspecs): Handle unavailable case.
+ (start_decl): Amend the logic handling suppression of nested
+ deprecation states to include unavailability.
+ (smallest_type_quals_location): Amend comment.
+ (grokdeclarator): Handle the unavailable deprecation state.
+ (declspecs_add_type): Set TREE_UNAVAILABLE from the decl specs.
+ * c-tree.h (struct c_declspecs): Add unavailable_p.
+ * c-typeck.c (build_component_ref): Handle unavailability.
+ (build_external_ref): Likewise.
+
+2021-09-01 Roger Sayle <roger@nextmovesoftware.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ PR c/79412
+ * c-decl.c (duplicate_decls): On significant mismatches, mark the
+ types of both (non-function) decls as error_mark_node, so that the
+ middle-end can see the code is malformed.
+ (free_attr_access_data): Don't process if the type has been set to
+ error_mark_node.
+
+2021-08-31 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_device): Parse device-modifiers 'device_num'
+ and 'ancestor' in 'target device' clauses.
+
+2021-08-23 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_num_tasks,
+ c_parser_omp_clause_grainsize): Parse the optional strict: modifier.
+
+2021-08-22 Martin Uecker <muecker@gwdg.de>
+
+ PR c/98397
+ * c-typeck.c (comp_target_types): Change pedwarn to pedwarn_c11
+ for pointers to arrays with qualifiers.
+ (build_conditional_expr): For C23 don't lose qualifiers for pointers
+ to arrays when the other pointer is a void pointer. Update warnings.
+ (convert_for_assignment): Update warnings for C2X when converting from
+ void* with qualifiers to a pointer to array with the same qualifiers.
+
+2021-08-20 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_error): New function.
+ (c_parser_pragma): Handle PRAGMA_OMP_ERROR.
+
+2021-08-20 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_depend_sink): Reject spurious
+ comma at the end of list.
+ (c_parser_omp_requires): Likewise.
+
+2021-08-19 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_requires): Don't call
+ c_parser_peek_2nd_token and optionally consume token if current
+ token is CPP_EOF, CPP_PRAGMA_EOL or CPP_CLOSE_PAREN.
+
+2021-08-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_nothing): New function.
+ (c_parser_pragma): Handle PRAGMA_OMP_NOTHING.
+
+2021-08-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_statement_after_labels): Add restart label
+ near the start of the function. If c_parser_pragma returns false,
+ goto restart.
+ (c_parser_pragma): For PRAGMA_OMP_CANCELLATION_POINT return what
+ c_parser_omp_cancellation_point returned. For PRAGMA_OMP_DECLARE
+ return what c_parser_omp_declare returned. Return true instead of
+ false after emitting errors that the directive is not allowed in
+ pragma_stmt context.
+ (c_parser_omp_ordered): Return true instead of
+ false after emitting errors that the directive is not allowed in
+ pragma_stmt context.
+ (c_parser_omp_target_update): Likewise.
+ (c_parser_omp_target_enter_data, c_parser_omp_target_exit_data):
+ Change return type from tree to bool, return false if the
+ directive should be ignored in pragma_stmt contexts.
+ (c_parser_omp_target): Adjust callers of c_parser_omp_target_*_data,
+ return their result directly.
+ (c_parser_omp_cancellation_point): Change return type from void to
+ bool, return false if the directive should be ignored in pragma_stmt
+ contexts.
+ (c_parser_omp_declare): Likewise.
+
+2021-08-17 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (OMP_SCOPE_CLAUSE_MASK): Define.
+ (c_parser_omp_scope): New function.
+ (c_parser_omp_construct): Handle PRAGMA_OMP_SCOPE.
+
+2021-08-12 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_name): Parse filter clause name.
+ (c_parser_omp_clause_filter): New function.
+ (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FILTER.
+ (OMP_MASKED_CLAUSE_MASK): Define.
+ (c_parser_omp_masked): New function.
+ (c_parser_omp_parallel): Handle parallel masked.
+ (c_parser_omp_construct): Handle PRAGMA_OMP_MASKED.
+ * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_FILTER.
+
+2021-08-12 Martin Uecker <muecker@gwdg.de>
+
+ PR c/101838
+ PR c/29970
+ * c-typeck.c (c_expr_sizeof_type): Evaluate
+ size expressions for structs of variable size.
+
+2021-08-12 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_proc_bind): Accept
+ 'primary' as alias for 'master'.
+
+2021-08-10 Martin Uecker <muecker@gwdg.de>
+
+ PR c/29970
+ * c-typeck.c (c_expr_sizeof_expr): Evaluate
+ size expressions for structs of variable size.
+
+2021-08-06 Tamar Christina <tamar.christina@arm.com>
+
+ * c-decl.c (c_simulate_enum_decl): Pass vec<> by pointer.
+ * c-tree.h (c_simulate_enum_decl): Likewise.
+
+2021-08-06 Martin Sebor <msebor@redhat.com>
+
+ * c-parser.c (c_parser_declaration_or_fndef): Adjust by-value function
+ vec arguments to by-reference.
+ (c_finish_omp_declare_simd): Same.
+ (c_parser_compound_statement_nostart): Same.
+ (c_parser_for_statement): Same.
+ (c_parser_objc_methodprotolist): Same.
+ (c_parser_oacc_routine): Same.
+ (c_parser_omp_for_loop): Same.
+ (c_parser_omp_declare_simd): Same.
+
+2021-07-21 Thomas Schwinge <thomas@codesourcery.com>
+ Joseph Myers <joseph@codesourcery.com>
+ Cesar Philippidis <cesar@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_name): Handle 'nohost'.
+ (c_parser_oacc_all_clauses): Handle 'PRAGMA_OACC_CLAUSE_NOHOST'.
+ (OACC_ROUTINE_CLAUSE_MASK): Add 'PRAGMA_OACC_CLAUSE_NOHOST'.
+ * c-typeck.c (c_finish_omp_clauses): Handle 'OMP_CLAUSE_NOHOST'.
+
+2021-07-20 Martin Sebor <msebor@redhat.com>
+
+ * c-tree.h (c_build_function_call_vec): Adjust by-value argument to
+ by-const-reference.
+ * c-typeck.c (c_build_function_call_vec): Same.
+
+2021-07-15 Martin Sebor <msebor@redhat.com>
+
+ PR c/101289
+ PR c/97548
+ * c-decl.c (get_parm_array_spec): Strip nops.
+
+2021-07-06 Martin Sebor <msebor@redhat.com>
+
+ * c-objc-common.c (c_tree_printer): Remove support for %G and %K.
+
+2021-07-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/101297
+ * c-parser.c (c_parser_omp_atomic): Consume comma only if it
+ appears before a CPP_NAME.
+
+2021-06-25 Martin Sebor <msebor@redhat.com>
+
+ * c-decl.c (pop_scope): Replace direct uses of TREE_NO_WARNING with
+ warning_suppressed_p, suppress_warning, and copy_no_warning.
+ (diagnose_mismatched_decls): Same.
+ (duplicate_decls): Same.
+ (grokdeclarator): Same.
+ (finish_function): Same.
+ (c_write_global_declarations_1): Same.
+ * c-fold.c (c_fully_fold_internal): Same.
+ * c-parser.c (c_parser_expr_no_commas): Same.
+ (c_parser_postfix_expression): Same.
+ * c-typeck.c (array_to_pointer_conversion): Same.
+ (function_to_pointer_conversion): Same.
+ (default_function_array_conversion): Same.
+ (convert_lvalue_to_rvalue): Same.
+ (default_conversion): Same.
+ (build_indirect_ref): Same.
+ (build_function_call_vec): Same.
+ (build_atomic_assign): Same.
+ (build_unary_op): Same.
+ (c_finish_return): Same.
+ (emit_side_effect_warnings): Same.
+ (c_finish_stmt_expr): Same.
+ (c_omp_clause_copy_ctor): Same.
+
+2021-06-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/101176
+ * c-parser.c (c_parser_has_attribute_expression): Set source range for
+ the result.
+
+2021-06-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/101171
+ * c-typeck.c (build_c_cast): Don't call note_integer_operands on
+ error_mark_node.
+
+2021-06-24 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (omp_split_clauses): Pass C_ORT_OMP_TARGET instead of
+ C_ORT_OMP for clauses on target construct.
+ (OMP_TARGET_CLAUSE_MASK): Add in_reduction clause.
+ (c_parser_omp_target): For non-combined target add
+ map (always, tofrom:) clauses for OMP_CLAUSE_IN_REDUCTION. Pass
+ C_ORT_OMP_TARGET to c_finish_omp_clauses.
+ * c-typeck.c (handle_omp_array_sections): Adjust ort handling
+ for addition of C_ORT_OMP_TARGET and simplify, mapping clauses are
+ never present on C_ORT_*DECLARE_SIMD.
+ (c_finish_omp_clauses): Likewise. Handle OMP_CLAUSE_IN_REDUCTION
+ on C_ORT_OMP_TARGET, set OMP_CLAUSE_MAP_IN_REDUCTION on
+ corresponding map clauses.
+
+2021-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR inline-asm/100785
+ * c-typeck.c (c_mark_addressable): Diagnose trying to make
+ bit-fields addressable.
+
+2021-06-15 Robin Dapp <rdapp@linux.ibm.com>
+
+ * c-decl.c (merge_decls): Copy DECL_USER_ALIGN if DECL_ALIGN is
+ similar.
+
+2021-06-14 Tobias Burnus <tobias@codesourcery.com>
+
+ PR c/100913
+ * c-parser.c (c_parser_omp_clause_affinity): No need to set iterator
+ var in the error case.
+
+2021-06-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR c/100920
+ * c-typeck.c (convert_for_assignment): Test fndecl_built_in_p to
+ spot built-in functions.
+
+2021-06-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/100902
+ * c-parser.c (c_parser_omp_target): Call c_omp_adjust_map_clauses
+ even when target is combined with other constructs.
+
+2021-06-06 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR c/100920
+ * c-decl.c (finish_struct): Fix thinko in previous change.
+ * c-typeck.c (convert_for_assignment): Do not warn on pointer
+ assignment and initialization for storage order purposes if the
+ RHS is a call to a DECL_IS_MALLOC function.
+
+2021-06-04 Martin Sebor <msebor@redhat.com>
+
+ PR c/100783
+ * c-objc-common.c (print_type): Handle erroneous types.
+
+2021-06-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/100859
+ * c-typeck.c (c_finish_omp_clauses): Move OMP_CLAUSE_AFFINITY
+ after depend only cases.
+
+2021-05-31 Richard Biener <rguenther@suse.de>
+
+ PR c++/88601
+ * c-decl.c (names_builtin_p): Handle RID_BUILTIN_SHUFFLEVECTOR.
+ * c-parser.c (c_parser_postfix_expression): Likewise.
+
+2021-05-28 Richard Biener <rguenther@suse.de>
+
+ PR c/100803
+ * gimple-parser.c (c_parser_gimple_paren_condition): Diagnose
+ invalid if conditions.
+
+2021-05-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/99928
+ * c-typeck.c (handle_omp_array_sections): Copy OMP_CLAUSE_MAP_IMPLICIT.
+ (c_finish_omp_clauses): Move not just OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT
+ marked clauses last, but also OMP_CLAUSE_MAP_IMPLICIT. Add
+ map_firstprivate_head bitmap, set it for GOMP_MAP_FIRSTPRIVATE_POINTER
+ maps and silently remove OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT if it is
+ present too. For OMP_CLAUSE_MAP_IMPLICIT silently remove the clause
+ if present in map_head, map_field_head or map_firstprivate_head
+ bitmaps.
+
+2021-05-28 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_affinity): New.
+ (c_parser_omp_clause_name, c_parser_omp_variable_list,
+ c_parser_omp_all_clauses, OMP_TASK_CLAUSE_MASK): Handle affinity clause.
+ * c-typeck.c (handle_omp_array_sections_1, handle_omp_array_sections,
+ c_finish_omp_clauses): Likewise.
+
+2021-05-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR c/100653
+ * c-decl.c (finish_struct): Warn for a union containing an aggregate
+ field with a differing scalar storage order.
+
+2021-05-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/99928
+ * c-typeck.c (c_finish_omp_clauses): Move firstprivate clauses with
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT to the end of the chain. Don't error
+ if a decl is mentioned both in map clause and in such firstprivate
+ clause unless OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET is also set.
+
+2021-05-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/99928
+ * c-parser.c (c_parser_omp_master): Set OMP_MASTER_COMBINED on
+ master when combined with taskloop.
+ (c_parser_omp_parallel): Don't set OMP_PARALLEL_COMBINED on
+ parallel master when not combined with taskloop.
+
+2021-05-18 Richard Biener <rguenther@suse.de>
+
+ PR c/100522
+ * gimple-parser.c (c_parser_gimple_postfix_expression_after_primary):
+ Diagnose calls to non-functions.
+ (c_parser_gimple_statement): Diagnose unexpected assignment RHS.
+
+2021-05-17 Richard Biener <rguenther@suse.de>
+
+ PR c/100625
+ * gimple-parser.c (c_parser_gimple_label): Avoid building
+ a GIMPLE label with NULL label decl.
+
+2021-05-13 Martin Sebor <msebor@redhat.com>
+
+ PR c/100550
+ * c-decl.c (get_parm_array_spec): Avoid erroneous VLA bounds.
+
+2021-05-12 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_map): Support map-type-modifier
+ 'close'.
+
+2021-05-10 Martin Liska <mliska@suse.cz>
+
+ * c-aux-info.c (affix_data_type): Use startswith
+ function instead of strncmp.
+ * c-typeck.c (build_function_call_vec): Likewise.
+ * gimple-parser.c (c_parser_gimple_parse_bb_spec): Likewise.
+
+2021-05-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-typeck.c (build_unary_op) <ADDR_EXPR>: Do not issue an error
+ on the address of a pointer field in a record with reverse SSO.
+
+2021-05-04 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-typeck.c (c_finish_omp_clauses): Accept float + complex
+ for || and && reductions.
+
+2021-04-29 Joseph Myers <joseph@codesourcery.com>
+
+ * c-typeck.c (function_types_compatible_p): For C2X, treat
+ unprototyped function as compatible with non-variadic prototyped
+ function even if some argument types are changed by the default
+ argument promotions.
+
+2021-04-15 Martin Sebor <msebor@redhat.com>
+
+ PR c/99420
+ PR c/99972
+ * c-decl.c (pushdecl): Always propagate type attribute.
+
+2021-04-15 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR c/98852
+ * c-typeck.c (c_common_type): Do not drop attributes that
+ affect type identity.
+
+2021-04-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/99990
+ * c-decl.c (finish_decl): Don't overwrite TREE_TYPE of
+ error_mark_node.
+
+2021-03-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/99565
+ * c-typeck.c (build_conditional_expr): Pass OEP_ADDRESS_OF_SAME_FIELD
+ to operand_equal_p.
+
+2021-03-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/99588
+ * c-typeck.c (mark_exp_read): Recognize what build_atomic_assign
+ with modifycode NOP_EXPR produces and mark the _Atomic var as read
+ if found.
+ (build_atomic_assign): For modifycode of NOP_EXPR, use COMPOUND_EXPRs
+ rather than STATEMENT_LIST. Otherwise call mark_exp_read on lhs.
+ Set TREE_SIDE_EFFECTS on the TARGET_EXPR.
+
2021-03-15 Tobias Burnus <tobias@codesourcery.com>
PR c++/99509
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index bae5757..81860cb 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -67,12 +67,12 @@ affix_data_type (const char *param)
for (;;)
{
- if (!strncmp (p, "volatile ", 9))
+ if (startswith (p, "volatile "))
{
p += 9;
continue;
}
- if (!strncmp (p, "const ", 6))
+ if (startswith (p, "const "))
{
p += 6;
continue;
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3b2241b..771efa3 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -73,13 +73,16 @@ enum decl_context
TYPENAME}; /* Typename (inside cast or sizeof) */
/* States indicating how grokdeclarator() should handle declspecs marked
- with __attribute__((deprecated)). An object declared as
- __attribute__((deprecated)) suppresses warnings of uses of other
- deprecated items. */
+ with __attribute__((deprecated)) or __attribute__((unavailable)).
+ An object declared as __attribute__((unavailable)) should suppress
+ any reports of being declared with unavailable or deprecated items.
+ An object declared as __attribute__((deprecated)) should suppress
+ warnings of uses of other deprecated items. */
enum deprecated_states {
DEPRECATED_NORMAL,
- DEPRECATED_SUPPRESS
+ DEPRECATED_SUPPRESS,
+ UNAVAILABLE_DEPRECATED_SUPPRESS
};
@@ -1295,7 +1298,7 @@ pop_scope (void)
case VAR_DECL:
/* Warnings for unused variables. */
if ((!TREE_USED (p) || !DECL_READ_P (p))
- && !TREE_NO_WARNING (p)
+ && !warning_suppressed_p (p, OPT_Wunused_but_set_variable)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p)
@@ -2159,8 +2162,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (DECL_IN_SYSTEM_HEADER (newdecl)
|| DECL_IN_SYSTEM_HEADER (olddecl)
- || TREE_NO_WARNING (newdecl)
- || TREE_NO_WARNING (olddecl))
+ || warning_suppressed_p (newdecl, OPT_Wpedantic)
+ || warning_suppressed_p (olddecl, OPT_Wpedantic))
return true; /* Allow OLDDECL to continue in use. */
if (variably_modified_type_p (newtype, NULL))
@@ -2620,6 +2623,9 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
SET_DECL_ALIGN (newdecl, DECL_ALIGN (olddecl));
DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
}
+ else if (DECL_ALIGN (olddecl) == DECL_ALIGN (newdecl)
+ && DECL_USER_ALIGN (olddecl) != DECL_USER_ALIGN (newdecl))
+ DECL_USER_ALIGN (newdecl) = 1;
if (DECL_WARN_IF_NOT_ALIGN (olddecl)
> DECL_WARN_IF_NOT_ALIGN (newdecl))
SET_DECL_WARN_IF_NOT_ALIGN (newdecl,
@@ -2641,6 +2647,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
+ /* Merge unavailability. */
+ if (TREE_UNAVAILABLE (newdecl))
+ TREE_UNAVAILABLE (olddecl) = 1;
+
/* If a decl is in a system header and the other isn't, keep the one on the
system header. Otherwise, keep source location of definition rather than
declaration and of prototype rather than non-prototype unless that
@@ -2953,7 +2963,18 @@ duplicate_decls (tree newdecl, tree olddecl)
if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
{
/* Avoid `unused variable' and other warnings for OLDDECL. */
- TREE_NO_WARNING (olddecl) = 1;
+ suppress_warning (olddecl, OPT_Wunused);
+ /* If the types are completely different, poison them both with
+ error_mark_node. */
+ if (TREE_CODE (TREE_TYPE (newdecl)) != TREE_CODE (TREE_TYPE (olddecl))
+ && olddecl != error_mark_node
+ && seen_error ())
+ {
+ if (TREE_CODE (olddecl) != FUNCTION_DECL)
+ TREE_TYPE (olddecl) = error_mark_node;
+ if (TREE_CODE (newdecl) != FUNCTION_DECL)
+ TREE_TYPE (newdecl) = error_mark_node;
+ }
return false;
}
@@ -3263,11 +3284,10 @@ pushdecl (tree x)
else
thistype = type;
b->u.type = TREE_TYPE (b->decl);
- if (TREE_CODE (b->decl) == FUNCTION_DECL
- && fndecl_built_in_p (b->decl))
- thistype
- = build_type_attribute_variant (thistype,
- TYPE_ATTRIBUTES (b->u.type));
+ /* Propagate the type attributes to the decl. */
+ thistype
+ = build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES (b->u.type));
TREE_TYPE (b->decl) = thistype;
bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
locus);
@@ -4879,6 +4899,7 @@ quals_from_declspecs (const struct c_declspecs *specs)
&& !specs->typedef_p
&& !specs->explicit_signed_p
&& !specs->deprecated_p
+ && !specs->unavailable_p
&& !specs->long_p
&& !specs->long_long_p
&& !specs->short_p
@@ -5081,9 +5102,14 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
tree expr = NULL_TREE;
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
- /* An object declared as __attribute__((deprecated)) suppresses
+ /* An object declared as __attribute__((unavailable)) suppresses
+ warnings and errors from __attribute__((deprecated/unavailable))
+ components.
+ An object declared as __attribute__((deprecated)) suppresses
warnings of uses of other deprecated items. */
- if (lookup_attribute ("deprecated", attributes))
+ if (lookup_attribute ("unavailable", attributes))
+ deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS;
+ else if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
@@ -5402,7 +5428,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
gcc_unreachable ();
}
- if (DECL_INITIAL (decl))
+ if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node)
TREE_TYPE (DECL_INITIAL (decl)) = type;
relayout_decl (decl);
@@ -5857,9 +5883,13 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
spec += buf;
break;
}
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts)))
+ /* Avoid invalid NELTS. */
+ return attrs;
/* Each variable VLA bound is represented by a dollar sign. */
spec += "$";
+ STRIP_NOPS (nelts);
vbchain = tree_cons (NULL_TREE, nelts, vbchain);
}
@@ -6216,7 +6246,7 @@ smallest_type_quals_location (const location_t *locations,
set to indicate whether operands in *EXPR can be used in constant
expressions.
DEPRECATED_STATE is a deprecated_states value indicating whether
- deprecation warnings should be suppressed.
+ deprecation/unavailability warnings should be suppressed.
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
@@ -6346,8 +6376,14 @@ grokdeclarator (const struct c_declarator *declarator,
if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
decl_context = PARM;
- if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (declspecs->type, declspecs->decl_attr);
+ if (deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS)
+ {
+ if (declspecs->unavailable_p)
+ error_unavailable_use (declspecs->type, declspecs->decl_attr);
+ else if (declspecs->deprecated_p
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (declspecs->type, declspecs->decl_attr);
+ }
if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope
@@ -7538,10 +7574,7 @@ grokdeclarator (const struct c_declarator *declarator,
FIELD_DECL, declarator->u.id.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !declarator->u.id.id)
- {
- TREE_NO_WARNING (decl) = 1;
- DECL_PADDING_P (decl) = 1;
- }
+ DECL_PADDING_P (decl) = 1;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -8851,6 +8884,22 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
= c_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
}
}
+
+ /* Warn on problematic type punning for storage order purposes. */
+ if (TREE_CODE (t) == UNION_TYPE
+ && TREE_CODE (field) == FIELD_DECL
+ && AGGREGATE_TYPE_P (TREE_TYPE (field)))
+ {
+ tree ftype = TREE_TYPE (field);
+ if (TREE_CODE (ftype) == ARRAY_TYPE)
+ ftype = strip_array_types (ftype);
+ if (RECORD_OR_UNION_TYPE_P (ftype)
+ && TYPE_REVERSE_STORAGE_ORDER (ftype)
+ != TYPE_REVERSE_STORAGE_ORDER (t))
+ warning_at (DECL_SOURCE_LOCATION (field),
+ OPT_Wscalar_storage_order,
+ "type punning toggles scalar storage order");
+ }
}
/* Now we have the truly final field list.
@@ -9360,7 +9409,7 @@ build_enumerator (location_t decl_loc, location_t loc,
tree
c_simulate_enum_decl (location_t loc, const char *name,
- vec<string_int_pair> values)
+ vec<string_int_pair> *values_ptr)
{
location_t saved_loc = input_location;
input_location = loc;
@@ -9370,6 +9419,7 @@ c_simulate_enum_decl (location_t loc, const char *name,
tree value_chain = NULL_TREE;
string_int_pair *value;
+ vec<string_int_pair> values = *values_ptr;
unsigned int i;
FOR_EACH_VEC_ELT (values, i, value)
{
@@ -10223,7 +10273,7 @@ finish_function (location_t end_loc)
&& targetm.warn_func_return (fndecl)
&& warning (OPT_Wreturn_type,
"no return statement in function returning non-void"))
- TREE_NO_WARNING (fndecl) = 1;
+ suppress_warning (fndecl, OPT_Wreturn_type);
/* Complain about parameters that are only set, but never otherwise used. */
if (warn_unused_but_set_parameter)
@@ -10238,7 +10288,7 @@ finish_function (location_t end_loc)
&& !DECL_READ_P (decl)
&& DECL_NAME (decl)
&& !DECL_ARTIFICIAL (decl)
- && !TREE_NO_WARNING (decl))
+ && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter))
warning_at (DECL_SOURCE_LOCATION (decl),
OPT_Wunused_but_set_parameter,
"parameter %qD set but not used", decl);
@@ -10538,6 +10588,7 @@ names_builtin_p (const char *name)
case RID_BUILTIN_CONVERTVECTOR:
case RID_BUILTIN_HAS_ATTRIBUTE:
case RID_BUILTIN_SHUFFLE:
+ case RID_BUILTIN_SHUFFLEVECTOR:
case RID_CHOOSE_EXPR:
case RID_OFFSETOF:
case RID_TYPES_COMPATIBLE_P:
@@ -10782,6 +10833,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->typespec_kind = spec.kind;
if (TREE_DEPRECATED (type))
specs->deprecated_p = true;
+ if (TREE_UNAVAILABLE (type))
+ specs->unavailable_p = true;
/* Handle type specifier keywords. */
if (TREE_CODE (type) == IDENTIFIER_NODE
@@ -12104,19 +12157,20 @@ c_write_global_declarations_1 (tree globals)
{
if (C_DECL_USED (decl))
{
+ /* TODO: Add OPT_Wundefined-inline. */
if (pedwarn (input_location, 0, "%q+F used but never defined",
decl))
- TREE_NO_WARNING (decl) = 1;
+ suppress_warning (decl /* OPT_Wundefined-inline. */);
}
/* For -Wunused-function warn about unused static prototypes. */
else if (warn_unused_function
&& ! DECL_ARTIFICIAL (decl)
- && ! TREE_NO_WARNING (decl))
+ && ! warning_suppressed_p (decl, OPT_Wunused_function))
{
if (warning (OPT_Wunused_function,
"%q+F declared %<static%> but never defined",
decl))
- TREE_NO_WARNING (decl) = 1;
+ suppress_warning (decl, OPT_Wunused_function);
}
}
@@ -12187,7 +12241,7 @@ free_attr_access_data ()
attr_access::free_lang_data (attrs);
tree fntype = TREE_TYPE (n->decl);
- if (!fntype)
+ if (!fntype || fntype == error_mark_node)
continue;
tree attrs = TYPE_ATTRIBUTES (fntype);
if (!attrs)
diff --git a/gcc/c/c-fold.c b/gcc/c/c-fold.c
index 68c74cc..0ebcb46 100644
--- a/gcc/c/c-fold.c
+++ b/gcc/c/c-fold.c
@@ -154,7 +154,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
tree orig_op0, orig_op1, orig_op2;
bool op0_const = true, op1_const = true, op2_const = true;
bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
- bool nowarning = TREE_NO_WARNING (expr);
+ bool nowarning = warning_suppressed_p (expr, OPT_Woverflow);
bool unused_p;
bool op0_lval = false;
source_range old_range;
@@ -670,13 +670,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
out:
/* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
have been done by this point, so remove them again. */
- nowarning |= TREE_NO_WARNING (ret);
+ nowarning |= warning_suppressed_p (ret, OPT_Woverflow);
STRIP_TYPE_NOPS (ret);
- if (nowarning && !TREE_NO_WARNING (ret))
+ if (nowarning && !warning_suppressed_p (ret, OPT_Woverflow))
{
if (!CAN_HAVE_LOCATION_P (ret))
ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
- TREE_NO_WARNING (ret) = 1;
+ suppress_warning (ret, OPT_Woverflow);
}
if (ret != expr)
{
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index a68249d..cdb2242 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -185,6 +185,12 @@ get_aka_type (tree type)
static void
print_type (c_pretty_printer *cpp, tree t, bool *quoted)
{
+ if (t == error_mark_node)
+ {
+ pp_string (cpp, _("{erroneous}"));
+ return;
+ }
+
gcc_assert (TYPE_P (t));
struct obstack *ob = pp_buffer (cpp)->obstack;
char *p = (char *) obstack_base (ob);
@@ -241,8 +247,6 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted)
%D: a general decl,
%E: an identifier or expression,
%F: a function declaration,
- %G: a Gimple statement,
- %K: a CALL_EXPR,
%T: a type.
%V: a list of type qualifiers from a tree.
%v: an explicit list of type qualifiers
@@ -263,19 +267,6 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
if (precision != 0 || wide)
return false;
- if (*spec == 'G')
- {
- percent_G_format (text);
- return true;
- }
-
- if (*spec == 'K')
- {
- t = va_arg (*text->args_ptr, tree);
- percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
- return true;
- }
-
if (*spec != 'v')
{
t = va_arg (*text->args_ptr, tree);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5cdeb21..d82c042 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1489,7 +1489,8 @@ static tree c_parser_std_attribute_specifier_sequence (c_parser *);
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
- bool, bool, tree *, vec<c_token>,
+ bool, bool, tree * = NULL,
+ vec<c_token> * = NULL,
bool have_attrs = false,
tree attrs = NULL,
struct oacc_routine_data * = NULL,
@@ -1577,15 +1578,17 @@ static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
static void c_parser_omp_cancel (c_parser *);
+static void c_parser_omp_nothing (c_parser *);
enum pragma_context { pragma_external, pragma_struct, pragma_param,
pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
-static void c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
+static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
static void c_parser_omp_end_declare_target (c_parser *);
-static void c_parser_omp_declare (c_parser *, enum pragma_context);
+static bool c_parser_omp_declare (c_parser *, enum pragma_context);
static void c_parser_omp_requires (c_parser *);
+static bool c_parser_omp_error (c_parser *, enum pragma_context);
static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
static void c_parser_oacc_routine (c_parser *, enum pragma_context);
@@ -1774,13 +1777,12 @@ c_parser_external_declaration (c_parser *parser)
an @interface or @protocol with prefix attributes). We can
only tell which after parsing the declaration specifiers, if
any, and the first declarator. */
- c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, vNULL);
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true);
break;
}
}
-static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
+static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
@@ -1890,11 +1892,15 @@ static void
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool static_assert_ok, bool empty_ok,
bool nested, bool start_attr_ok,
- tree *objc_foreach_object_declaration,
- vec<c_token> omp_declare_simd_clauses,
- bool have_attrs, tree attrs,
- struct oacc_routine_data *oacc_routine_data,
- bool *fallthru_attr_p)
+ tree *objc_foreach_object_declaration
+ /* = NULL */,
+ vec<c_token> *omp_declare_simd_clauses
+ /* = NULL */,
+ bool have_attrs /* = false */,
+ tree attrs /* = NULL_TREE */,
+ struct oacc_routine_data *oacc_routine_data
+ /* = NULL */,
+ bool *fallthru_attr_p /* = NULL */)
{
struct c_declspecs *specs;
tree prefix_attrs;
@@ -2150,7 +2156,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
C_DTR_NORMAL, &dummy);
if (declarator == NULL)
{
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
omp_declare_simd_clauses);
if (oacc_routine_data)
@@ -2250,7 +2256,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
chainon (postfix_attrs, all_prefix_attrs));
if (!d)
d = error_mark_node;
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
}
@@ -2262,7 +2268,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
chainon (postfix_attrs, all_prefix_attrs));
if (!d)
d = error_mark_node;
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
init_loc = c_parser_peek_token (parser)->location;
@@ -2342,7 +2348,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
warn_parm_array_mismatch (lastloc, d, parms);
}
}
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
{
tree parms = NULL_TREE;
if (d && TREE_CODE (d) == FUNCTION_DECL)
@@ -2496,9 +2502,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
while (c_parser_next_token_is_not (parser, CPP_EOF)
&& c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
c_parser_declaration_or_fndef (parser, false, false, false,
- true, false, NULL, vNULL);
+ true, false);
store_parm_decls ();
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
omp_declare_simd_clauses);
if (oacc_routine_data)
@@ -5699,7 +5705,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
bool fallthru_attr_p = false;
c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
true, true, true, NULL,
- vNULL, have_std_attrs, std_attrs,
+ NULL, have_std_attrs, std_attrs,
NULL, &fallthru_attr_p);
if (last_stmt && !fallthru_attr_p)
@@ -5731,7 +5737,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
last_label = false;
mark_valid_location_for_stdc_pragma (false);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, vNULL);
+ true);
/* Following the old parser, __extension__ does not
disable this diagnostic. */
restore_extension_diagnostics (ext);
@@ -6096,6 +6102,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
add_debug_begin_stmt (loc);
+ restart:
switch (c_parser_peek_token (parser)->type)
{
case CPP_OPEN_BRACE:
@@ -6242,7 +6249,8 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_consume_token (parser);
break;
case CPP_PRAGMA:
- c_parser_pragma (parser, pragma_stmt, if_p);
+ if (!c_parser_pragma (parser, pragma_stmt, if_p))
+ goto restart;
break;
default:
expr_stmt:
@@ -6782,7 +6790,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
|| c_parser_nth_token_starts_std_attributes (parser, 1))
{
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- &object_expression, vNULL);
+ &object_expression);
parser->objc_could_be_foreach_context = false;
if (c_parser_next_token_is_keyword (parser, RID_IN))
@@ -6813,7 +6821,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
ext = disable_extension_diagnostics ();
c_parser_consume_token (parser);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, &object_expression, vNULL);
+ true, &object_expression);
parser->objc_could_be_foreach_context = false;
restore_extension_diagnostics (ext);
@@ -7558,7 +7566,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
ret.original_code = MODIFY_EXPR;
else
{
- TREE_NO_WARNING (ret.value) = 1;
+ suppress_warning (ret.value, OPT_Wparentheses);
ret.original_code = ERROR_MARK;
}
ret.original_type = NULL;
@@ -7655,10 +7663,21 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
location_t loc1 = make_location (exp1.get_start (), exp1.src_range);
location_t loc2 = make_location (exp2.get_start (), exp2.src_range);
- ret.value = build_conditional_expr (colon_loc, cond.value,
- cond.original_code == C_MAYBE_CONST_EXPR,
- exp1.value, exp1.original_type, loc1,
- exp2.value, exp2.original_type, loc2);
+ if (__builtin_expect (omp_atomic_lhs != NULL, 0)
+ && (TREE_CODE (cond.value) == GT_EXPR
+ || TREE_CODE (cond.value) == LT_EXPR
+ || TREE_CODE (cond.value) == EQ_EXPR)
+ && c_tree_equal (exp2.value, omp_atomic_lhs)
+ && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
+ || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
+ ret.value = build3_loc (colon_loc, COND_EXPR, TREE_TYPE (omp_atomic_lhs),
+ cond.value, exp1.value, exp2.value);
+ else
+ ret.value
+ = build_conditional_expr (colon_loc, cond.value,
+ cond.original_code == C_MAYBE_CONST_EXPR,
+ exp1.value, exp1.original_type, loc1,
+ exp2.value, exp2.original_type, loc2);
ret.original_code = ERROR_MARK;
if (exp1.value == error_mark_node || exp2.value == error_mark_node)
ret.original_type = NULL;
@@ -7841,15 +7860,27 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
= convert_lvalue_to_rvalue (stack[sp].loc, \
stack[sp].expr, true, true); \
if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1 \
- && c_parser_peek_token (parser)->type == CPP_SEMICOLON \
- && ((1 << stack[sp].prec) \
- & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \
- | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \
+ && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
+ && ((1 << stack[sp].prec) \
+ & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
+ | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
+ | (1 << PREC_ADD) | (1 << PREC_MULT) \
+ | (1 << PREC_EQ)))) \
+ || ((c_parser_next_token_is (parser, CPP_QUERY) \
+ || (omp_atomic_lhs == void_list_node \
+ && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
+ && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
&& stack[sp].op != TRUNC_MOD_EXPR \
+ && stack[sp].op != GE_EXPR \
+ && stack[sp].op != LE_EXPR \
+ && stack[sp].op != NE_EXPR \
&& stack[0].expr.value != error_mark_node \
&& stack[1].expr.value != error_mark_node \
- && (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
- || c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \
+ && (omp_atomic_lhs == void_list_node \
+ || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
+ || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
+ || (stack[sp].op == EQ_EXPR \
+ && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
{ \
tree t = make_node (stack[1].op); \
TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
@@ -8406,6 +8437,7 @@ c_parser_has_attribute_expression (c_parser *parser)
{
gcc_assert (c_parser_next_token_is_keyword (parser,
RID_BUILTIN_HAS_ATTRIBUTE));
+ location_t start = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
c_inhibit_evaluation_warnings++;
@@ -8484,6 +8516,7 @@ c_parser_has_attribute_expression (c_parser *parser)
parser->translate_strings_p = save_translate_strings_p;
+ location_t finish = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
c_parser_consume_token (parser);
else
@@ -8512,6 +8545,7 @@ c_parser_has_attribute_expression (c_parser *parser)
else
result.value = boolean_false_node;
+ set_c_expr_source_range (&result, start, finish);
return result;
}
@@ -9085,7 +9119,7 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_consume_token (parser);
expr = c_parser_expression (parser);
if (TREE_CODE (expr.value) == MODIFY_EXPR)
- TREE_NO_WARNING (expr.value) = 1;
+ suppress_warning (expr.value, OPT_Wparentheses);
if (expr.original_code != C_MAYBE_CONST_EXPR
&& expr.original_code != SIZEOF_EXPR)
expr.original_code = ERROR_MARK;
@@ -10000,6 +10034,44 @@ c_parser_postfix_expression (c_parser *parser)
set_c_expr_source_range (&expr, loc, close_paren_loc);
break;
}
+ case RID_BUILTIN_SHUFFLEVECTOR:
+ {
+ vec<c_expr_t, va_gc> *cexpr_list;
+ unsigned int i;
+ c_expr_t *p;
+ location_t close_paren_loc;
+
+ c_parser_consume_token (parser);
+ if (!c_parser_get_builtin_args (parser,
+ "__builtin_shufflevector",
+ &cexpr_list, false,
+ &close_paren_loc))
+ {
+ expr.set_error ();
+ break;
+ }
+
+ FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
+ *p = convert_lvalue_to_rvalue (loc, *p, true, true);
+
+ if (vec_safe_length (cexpr_list) < 3)
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_shuffle%>");
+ expr.set_error ();
+ }
+ else
+ {
+ auto_vec<tree, 16> mask;
+ for (i = 2; i < cexpr_list->length (); ++i)
+ mask.safe_push ((*cexpr_list)[i].value);
+ expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
+ (*cexpr_list)[1].value,
+ mask);
+ }
+ set_c_expr_source_range (&expr, loc, close_paren_loc);
+ break;
+ }
case RID_BUILTIN_CONVERTVECTOR:
{
location_t start_loc = loc;
@@ -11236,7 +11308,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
}
else
c_parser_declaration_or_fndef (parser, false, false, true,
- false, true, NULL, vNULL);
+ false, true);
break;
}
}
@@ -12301,7 +12373,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
"%<#pragma %s%> may only be used in compound "
"statements", construct);
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return false;
+ return true;
}
goto bad_stmt;
}
@@ -12392,8 +12464,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
return false;
case PRAGMA_OMP_CANCELLATION_POINT:
- c_parser_omp_cancellation_point (parser, context);
- return false;
+ return c_parser_omp_cancellation_point (parser, context);
case PRAGMA_OMP_THREADPRIVATE:
c_parser_omp_threadprivate (parser);
@@ -12421,8 +12492,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
return false;
case PRAGMA_OMP_DECLARE:
- c_parser_omp_declare (parser, context);
- return false;
+ return c_parser_omp_declare (parser, context);
case PRAGMA_OMP_REQUIRES:
if (context != pragma_external)
@@ -12435,6 +12505,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_omp_requires (parser);
return false;
+ case PRAGMA_OMP_NOTHING:
+ c_parser_omp_nothing (parser);
+ return false;
+
+ case PRAGMA_OMP_ERROR:
+ return c_parser_omp_error (parser, context);
+
case PRAGMA_OMP_ORDERED:
return c_parser_omp_ordered (parser, context, if_p);
@@ -12460,7 +12537,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
else
c_parser_do_statement (parser, ivdep, unroll);
}
- return false;
+ return true;
case PRAGMA_UNROLL:
{
@@ -12484,7 +12561,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
else
c_parser_do_statement (parser, ivdep, unroll);
}
- return false;
+ return true;
case PRAGMA_GCC_PCH_PREPROCESS:
c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
@@ -12601,7 +12678,9 @@ c_parser_omp_clause_name (c_parser *parser)
switch (p[0])
{
case 'a':
- if (!strcmp ("aligned", p))
+ if (!strcmp ("affinity", p))
+ result = PRAGMA_OMP_CLAUSE_AFFINITY;
+ else if (!strcmp ("aligned", p))
result = PRAGMA_OMP_CLAUSE_ALIGNED;
else if (!strcmp ("allocate", p))
result = PRAGMA_OMP_CLAUSE_ALLOCATE;
@@ -12649,7 +12728,9 @@ c_parser_omp_clause_name (c_parser *parser)
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
break;
case 'f':
- if (!strcmp ("final", p))
+ if (!strcmp ("filter", p))
+ result = PRAGMA_OMP_CLAUSE_FILTER;
+ else if (!strcmp ("final", p))
result = PRAGMA_OMP_CLAUSE_FINAL;
else if (!strcmp ("finalize", p))
result = PRAGMA_OACC_CLAUSE_FINALIZE;
@@ -12701,6 +12782,8 @@ c_parser_omp_clause_name (c_parser *parser)
result = PRAGMA_OACC_CLAUSE_NO_CREATE;
else if (!strcmp ("nogroup", p))
result = PRAGMA_OMP_CLAUSE_NOGROUP;
+ else if (!strcmp ("nohost", p))
+ result = PRAGMA_OACC_CLAUSE_NOHOST;
else if (!strcmp ("nontemporal", p))
result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
else if (!strcmp ("notinbranch", p))
@@ -12900,7 +12983,7 @@ c_parser_omp_variable_list (c_parser *parser,
while (1)
{
bool array_section_p = false;
- if (kind == OMP_CLAUSE_DEPEND)
+ if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
{
if (c_parser_next_token_is_not (parser, CPP_NAME)
|| c_parser_peek_token (parser)->id_kind != C_ID_ID)
@@ -13040,6 +13123,7 @@ c_parser_omp_variable_list (c_parser *parser,
t = build_component_ref (op_loc, t, ident, comp_loc);
}
/* FALLTHROUGH */
+ case OMP_CLAUSE_AFFINITY:
case OMP_CLAUSE_DEPEND:
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
@@ -13090,7 +13174,7 @@ c_parser_omp_variable_list (c_parser *parser,
t = tree_cons (low_bound, length, t);
}
- if (kind == OMP_CLAUSE_DEPEND
+ if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
&& t != error_mark_node
&& parser->tokens_avail != 2)
{
@@ -13130,7 +13214,7 @@ c_parser_omp_variable_list (c_parser *parser,
else
list = tree_cons (t, NULL_TREE, list);
- if (kind == OMP_CLAUSE_DEPEND)
+ if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
{
parser->tokens = &parser->tokens_buf[0];
parser->tokens_avail = tokens_avail;
@@ -13725,7 +13809,10 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
}
/* OpenMP 4.5:
- num_tasks ( expression ) */
+ num_tasks ( expression )
+
+ OpenMP 5.1:
+ num_tasks ( strict : expression ) */
static tree
c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
@@ -13734,6 +13821,17 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
matching_parens parens;
if (parens.require_open (parser))
{
+ bool strict = false;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "strict") == 0)
+ {
+ strict = true;
+ c_parser_consume_token (parser);
+ c_parser_consume_token (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);
@@ -13763,6 +13861,7 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
+ OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
}
@@ -13771,7 +13870,10 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
}
/* OpenMP 4.5:
- grainsize ( expression ) */
+ grainsize ( expression )
+
+ OpenMP 5.1:
+ grainsize ( strict : expression ) */
static tree
c_parser_omp_clause_grainsize (c_parser *parser, tree list)
@@ -13780,6 +13882,17 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list)
matching_parens parens;
if (parens.require_open (parser))
{
+ bool strict = false;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "strict") == 0)
+ {
+ strict = true;
+ c_parser_consume_token (parser);
+ c_parser_consume_token (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);
@@ -13809,6 +13922,7 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list)
c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
+ OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
}
@@ -13898,6 +14012,38 @@ c_parser_omp_clause_hint (c_parser *parser, tree list)
return list;
}
+/* OpenMP 5.1:
+ filter ( integer-expression ) */
+
+static tree
+c_parser_omp_clause_filter (c_parser *parser, tree list)
+{
+ location_t hint_loc = c_parser_peek_token (parser)->location;
+ matching_parens parens;
+ if (parens.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);
+ tree c, t = expr.value;
+ t = c_fully_fold (t, false, NULL);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+ parens.skip_until_found_close (parser);
+ check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter");
+
+ c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
+ OMP_CLAUSE_FILTER_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
/* OpenMP 4.5:
defaultmap ( tofrom : scalar )
@@ -15392,7 +15538,9 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
}
- if (c_parser_next_token_is_not (parser, CPP_COMMA))
+ if (c_parser_next_token_is_not (parser, CPP_COMMA)
+ || c_parser_peek_2nd_token (parser)->type != CPP_NAME
+ || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
break;
c_parser_consume_token (parser);
@@ -15508,6 +15656,67 @@ c_parser_omp_iterators (c_parser *parser)
return ret ? ret : error_mark_node;
}
+/* OpenMP 5.0:
+ affinity ( [aff-modifier :] variable-list )
+ aff-modifier:
+ iterator ( iterators-definition ) */
+
+static tree
+c_parser_omp_clause_affinity (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ tree nl, iterators = NULL_TREE;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ bool parse_iter = ((strcmp ("iterator", p) == 0)
+ && (c_parser_peek_2nd_token (parser)->type
+ == CPP_OPEN_PAREN));
+ if (parse_iter)
+ {
+ unsigned n = 3;
+ parse_iter = (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));
+ }
+ if (parse_iter)
+ {
+ iterators = c_parser_omp_iterators (parser);
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ {
+ if (iterators)
+ pop_scope ();
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ }
+ }
+ nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_AFFINITY,
+ list);
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators != error_mark_node)
+ {
+ TREE_VEC_ELT (iterators, 5) = block;
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
+ OMP_CLAUSE_DECL (c));
+ }
+ }
+
+ parens.skip_until_found_close (parser);
+ return nl;
+}
+
+
/* OpenMP 4.0:
depend ( depend-kind: variable-list )
@@ -15643,54 +15852,83 @@ c_parser_omp_clause_depend (c_parser *parser, tree list)
map-kind:
alloc | to | from | tofrom | release | delete
- map ( always [,] map-kind: variable-list ) */
+ map ( always [,] map-kind: variable-list )
+
+ OpenMP 5.0:
+ map ( [map-type-modifier[,] ...] map-kind: variable-list )
+
+ map-type-modifier:
+ always | close */
static tree
c_parser_omp_clause_map (c_parser *parser, tree list)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
enum gomp_map_kind kind = GOMP_MAP_TOFROM;
- int always = 0;
- enum c_id_kind always_id_kind = C_ID_NONE;
- location_t always_loc = UNKNOWN_LOCATION;
- tree always_id = NULL_TREE;
tree nl, c;
matching_parens parens;
if (!parens.require_open (parser))
return list;
- if (c_parser_next_token_is (parser, CPP_NAME))
+ int pos = 1;
+ int map_kind_pos = 0;
+ while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ {
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON)
+ {
+ map_kind_pos = pos;
+ break;
+ }
+
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ pos++;
+ pos++;
+ }
+
+ int always_modifier = 0;
+ int close_modifier = 0;
+ for (int pos = 1; pos < map_kind_pos; ++pos)
{
c_token *tok = c_parser_peek_token (parser);
+
+ if (tok->type == CPP_COMMA)
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+
const char *p = IDENTIFIER_POINTER (tok->value);
- always_id_kind = tok->id_kind;
- always_loc = tok->location;
- always_id = tok->value;
if (strcmp ("always", p) == 0)
{
- c_token *sectok = c_parser_peek_2nd_token (parser);
- if (sectok->type == CPP_COMMA)
+ if (always_modifier)
{
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- always = 2;
+ c_parser_error (parser, "too many %<always%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
}
- else if (sectok->type == CPP_NAME)
+ always_modifier++;
+ }
+ else if (strcmp ("close", p) == 0)
+ {
+ if (close_modifier)
{
- p = IDENTIFIER_POINTER (sectok->value);
- if (strcmp ("alloc", p) == 0
- || strcmp ("to", p) == 0
- || strcmp ("from", p) == 0
- || strcmp ("tofrom", p) == 0
- || strcmp ("release", p) == 0
- || strcmp ("delete", p) == 0)
- {
- c_parser_consume_token (parser);
- always = 1;
- }
+ c_parser_error (parser, "too many %<close%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
}
+ close_modifier++;
+ }
+ else
+ {
+ c_parser_error (parser, "%<#pragma omp target%> with "
+ "modifier other than %<always%> or %<close%>"
+ "on %<map%> clause");
+ parens.skip_until_found_close (parser);
+ return list;
}
+
+ c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_NAME)
@@ -15700,11 +15938,11 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
if (strcmp ("alloc", p) == 0)
kind = GOMP_MAP_ALLOC;
else if (strcmp ("to", p) == 0)
- kind = always ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO;
+ kind = always_modifier ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO;
else if (strcmp ("from", p) == 0)
- kind = always ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM;
+ kind = always_modifier ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM;
else if (strcmp ("tofrom", p) == 0)
- kind = always ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM;
+ kind = always_modifier ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM;
else if (strcmp ("release", p) == 0)
kind = GOMP_MAP_RELEASE;
else if (strcmp ("delete", p) == 0)
@@ -15719,35 +15957,6 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
c_parser_consume_token (parser);
c_parser_consume_token (parser);
}
- else if (always)
- {
- if (always_id_kind != C_ID_ID)
- {
- c_parser_error (parser, "expected identifier");
- parens.skip_until_found_close (parser);
- return list;
- }
-
- tree t = lookup_name (always_id);
- if (t == NULL_TREE)
- {
- undeclared_variable (always_loc, always_id);
- t = error_mark_node;
- }
- if (t != error_mark_node)
- {
- tree u = build_omp_clause (clause_loc, OMP_CLAUSE_MAP);
- OMP_CLAUSE_DECL (u) = t;
- OMP_CLAUSE_CHAIN (u) = list;
- OMP_CLAUSE_SET_MAP_KIND (u, kind);
- list = u;
- }
- if (always == 1)
- {
- parens.skip_until_found_close (parser);
- return list;
- }
- }
nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list);
@@ -15759,37 +15968,87 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
}
/* OpenMP 4.0:
- device ( expression ) */
+ device ( expression )
+
+ OpenMP 5.0:
+ device ( [device-modifier :] integer-expression )
+
+ device-modifier:
+ ancestor | device_num */
static tree
c_parser_omp_clause_device (c_parser *parser, tree list)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.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);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
+ location_t expr_loc;
+ c_expr expr;
+ tree c, t;
+ bool ancestor = false;
- parens.skip_until_found_close (parser);
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ c_token *tok = c_parser_peek_token (parser);
+ const char *p = IDENTIFIER_POINTER (tok->value);
+ if (strcmp ("ancestor", p) == 0)
{
- c_parser_error (parser, "expected integer expression");
+ /* A requires directive with the reverse_offload clause must be
+ specified. */
+ if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
+ {
+ error_at (tok->location, "%<ancestor%> device modifier not "
+ "preceded by %<requires%> directive "
+ "with %<reverse_offload%> clause");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ ancestor = true;
+ }
+ else if (strcmp ("device_num", p) == 0)
+ ;
+ else
+ {
+ error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
+ parens.skip_until_found_close (parser);
return list;
}
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ }
+
+ 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);
+ t = expr.value;
+ t = c_fully_fold (t, false, NULL);
- check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
+ parens.skip_until_found_close (parser);
- c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
- OMP_CLAUSE_DEVICE_ID (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
}
+ if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
+ {
+ error_at (expr_loc, "the %<device%> clause expression must evaluate to "
+ "%<1%>");
+ return list;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
+
+ OMP_CLAUSE_DEVICE_ID (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
+
+ list = c;
return list;
}
@@ -15848,7 +16107,8 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
proc_bind ( proc-bind-kind )
proc-bind-kind:
- master | close | spread */
+ primary | master | close | spread
+ where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
static tree
c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
@@ -15864,7 +16124,9 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp ("master", p) == 0)
+ if (strcmp ("primary", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
+ else if (strcmp ("master", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_MASTER;
else if (strcmp ("close", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_CLOSE;
@@ -16143,6 +16405,11 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
c_name = "no_create";
break;
+ case PRAGMA_OACC_CLAUSE_NOHOST:
+ clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_NOHOST,
+ clauses);
+ c_name = "nohost";
+ break;
case PRAGMA_OACC_CLAUSE_NUM_GANGS:
clauses = c_parser_oacc_single_int_clause (parser,
OMP_CLAUSE_NUM_GANGS,
@@ -16291,6 +16558,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_omp_clause_detach (parser, clauses);
c_name = "detach";
break;
+ case PRAGMA_OMP_CLAUSE_FILTER:
+ clauses = c_parser_omp_clause_filter (parser, clauses);
+ c_name = "filter";
+ break;
case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
clauses = c_parser_omp_clause_firstprivate (parser, clauses);
c_name = "firstprivate";
@@ -16474,6 +16745,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_omp_clause_linear (parser, clauses);
c_name = "linear";
break;
+ case PRAGMA_OMP_CLAUSE_AFFINITY:
+ clauses = c_parser_omp_clause_affinity (parser, clauses);
+ c_name = "affinity";
+ break;
case PRAGMA_OMP_CLAUSE_DEPEND:
clauses = c_parser_omp_clause_depend (parser, clauses);
c_name = "depend";
@@ -17070,7 +17345,8 @@ c_parser_oacc_compute (location_t loc, c_parser *parser,
( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) )
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
/* Parse an OpenACC routine directive. For named directives, we apply
immediately to the named function. For unnamed ones we then parse
@@ -17164,12 +17440,12 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
while (c_parser_next_token_is (parser, CPP_KEYWORD)
&& c_parser_peek_token (parser)->keyword == RID_EXTENSION);
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, vNULL, false, NULL, &data);
+ NULL, NULL, false, NULL, &data);
restore_extension_diagnostics (ext);
}
else
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, vNULL, false, NULL, &data);
+ NULL, NULL, false, NULL, &data);
}
}
@@ -17402,14 +17678,45 @@ c_parser_omp_allocate (location_t loc, c_parser *parser)
capture-block:
{ v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
- where x and v are lvalue expressions with scalar type.
+ OpenMP 5.1:
+ # pragma omp atomic compare new-line
+ conditional-update-atomic
+
+ # pragma omp atomic compare capture new-line
+ conditional-update-capture-atomic
+
+ conditional-update-atomic:
+ cond-expr-stmt | cond-update-stmt
+ cond-expr-stmt:
+ x = expr ordop x ? expr : x;
+ x = x ordop expr ? expr : x;
+ x = x == e ? d : x;
+ cond-update-stmt:
+ if (expr ordop x) { x = expr; }
+ if (x ordop expr) { x = expr; }
+ if (x == e) { x = d; }
+ ordop:
+ <, >
+ conditional-update-capture-atomic:
+ v = cond-expr-stmt
+ { v = x; cond-expr-stmt }
+ { cond-expr-stmt v = x; }
+ { v = x; cond-update-stmt }
+ { cond-update-stmt v = x; }
+ if (x == e) { x = d; } else { v = x; }
+ { r = x == e; if (r) { x = d; } }
+ { r = x == e; if (r) { x = d; } else { v = x; } }
+
+ where x, r and v are lvalue expressions with scalar type,
+ expr, e and d are expressions with scalar type and e might be
+ the same as v.
LOC is the location of the #pragma token. */
static void
c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
{
- tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
+ tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
@@ -17421,10 +17728,18 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
bool non_lvalue_p;
bool first = true;
tree clauses = NULL_TREE;
+ bool capture = false;
+ bool compare = false;
+ bool weak = false;
+ enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+ bool no_semicolon = false;
+ bool extra_scope = false;
while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
{
- if (!first && c_parser_next_token_is (parser, CPP_COMMA))
+ if (!first
+ && c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
c_parser_consume_token (parser);
first = false;
@@ -17437,6 +17752,10 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
enum tree_code new_code = ERROR_MARK;
enum omp_memory_order new_memory_order
= OMP_MEMORY_ORDER_UNSPECIFIED;
+ bool new_capture = false;
+ bool new_compare = false;
+ bool new_weak = false;
+ enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
if (!strcmp (p, "read"))
new_code = OMP_ATOMIC_READ;
@@ -17444,7 +17763,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
new_code = NOP_EXPR;
else if (!strcmp (p, "update"))
new_code = OMP_ATOMIC;
- else if (!strcmp (p, "capture"))
+ else if (openacc && !strcmp (p, "capture"))
new_code = OMP_ATOMIC_CAPTURE_NEW;
else if (openacc)
{
@@ -17452,6 +17771,47 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
"or %<capture%> clause");
}
+ else if (!strcmp (p, "capture"))
+ new_capture = true;
+ else if (!strcmp (p, "compare"))
+ new_compare = true;
+ else if (!strcmp (p, "weak"))
+ new_weak = true;
+ else if (!strcmp (p, "fail"))
+ {
+ matching_parens parens;
+
+ c_parser_consume_token (parser);
+ if (!parens.require_open (parser))
+ continue;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *q
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ if (!strcmp (q, "seq_cst"))
+ new_fail = OMP_MEMORY_ORDER_SEQ_CST;
+ else if (!strcmp (q, "acquire"))
+ new_fail = OMP_MEMORY_ORDER_ACQUIRE;
+ else if (!strcmp (q, "relaxed"))
+ new_fail = OMP_MEMORY_ORDER_RELAXED;
+ }
+
+ if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ {
+ c_parser_consume_token (parser);
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ error_at (cloc, "too many %qs clauses", "fail");
+ else
+ fail = new_fail;
+ }
+ else
+ c_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
+ "or %<relaxed%>");
+ parens.skip_until_found_close (parser);
+ continue;
+ }
else if (!strcmp (p, "seq_cst"))
new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
else if (!strcmp (p, "acq_rel"))
@@ -17472,8 +17832,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
{
p = NULL;
error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
- "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
- "%<release%>, %<relaxed%> or %<hint%> clause");
+ "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
+ "%<seq_cst%>, %<acq_rel%>, %<release%>, "
+ "%<relaxed%> or %<hint%> clause");
}
if (p)
{
@@ -17496,6 +17857,27 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
else
memory_order = new_memory_order;
}
+ else if (new_capture)
+ {
+ if (capture)
+ error_at (cloc, "too many %qs clauses", "capture");
+ else
+ capture = true;
+ }
+ else if (new_compare)
+ {
+ if (compare)
+ error_at (cloc, "too many %qs clauses", "compare");
+ else
+ compare = true;
+ }
+ else if (new_weak)
+ {
+ if (weak)
+ error_at (cloc, "too many %qs clauses", "weak");
+ else
+ weak = true;
+ }
c_parser_consume_token (parser);
continue;
}
@@ -17506,6 +17888,30 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
if (code == ERROR_MARK)
code = OMP_ATOMIC;
+ if (capture)
+ {
+ if (code != OMP_ATOMIC)
+ error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+ "clauses", "capture");
+ else
+ code = OMP_ATOMIC_CAPTURE_NEW;
+ }
+ if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
+ {
+ error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+ "clauses", "compare");
+ compare = false;
+ }
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
+ {
+ error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
+ fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+ }
+ if (weak && !compare)
+ {
+ error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
+ weak = false;
+ }
if (openacc)
memory_order = OMP_MEMORY_ORDER_RELAXED;
else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
@@ -17530,7 +17936,6 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
memory_order = OMP_MEMORY_ORDER_ACQUIRE;
break;
case NOP_EXPR: /* atomic write */
- case OMP_ATOMIC:
memory_order = OMP_MEMORY_ORDER_RELEASE;
break;
default:
@@ -17546,36 +17951,32 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
switch (code)
{
case OMP_ATOMIC_READ:
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_RELEASE)
+ if (memory_order == OMP_MEMORY_ORDER_RELEASE)
{
error_at (loc, "%<#pragma omp atomic read%> incompatible with "
- "%<acq_rel%> or %<release%> clauses");
+ "%<release%> clause");
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
}
+ else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
+ memory_order = OMP_MEMORY_ORDER_ACQUIRE;
break;
case NOP_EXPR: /* atomic write */
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+ if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
{
error_at (loc, "%<#pragma omp atomic write%> incompatible with "
- "%<acq_rel%> or %<acquire%> clauses");
- memory_order = OMP_MEMORY_ORDER_SEQ_CST;
- }
- break;
- case OMP_ATOMIC:
- /* case OMP_ATOMIC_CAPTURE_NEW: - or update to OpenMP 5.1 */
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
- {
- error_at (loc, "%<#pragma omp atomic update%> incompatible with "
- "%<acq_rel%> or %<acquire%> clauses");
+ "%<acquire%> clause");
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
}
+ else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
+ memory_order = OMP_MEMORY_ORDER_RELEASE;
break;
default:
break;
}
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ memory_order
+ = (enum omp_memory_order) (memory_order
+ | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
switch (code)
{
@@ -17624,6 +18025,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
c_parser_consume_token (parser);
structured_block = true;
}
+ else if (compare
+ && c_parser_next_token_is_keyword (parser, RID_IF))
+ break;
else
{
v = c_parser_cast_expression (parser, NULL).value;
@@ -17635,6 +18039,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
v = non_lvalue (v);
if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
goto saw_error;
+ if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
+ {
+ eloc = c_parser_peek_token (parser)->location;
+ error_at (eloc, "expected expression");
+ goto saw_error;
+ }
}
break;
default:
@@ -17644,6 +18054,179 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
/* For structured_block case we don't know yet whether
old or new x should be captured. */
restart:
+ if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
+ {
+ c_parser_consume_token (parser);
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ goto saw_error;
+ eloc = c_parser_peek_token (parser)->location;
+ c_expr cmp_expr;
+ if (r)
+ {
+ cmp_expr = c_parser_cast_expression (parser, NULL);
+ cmp_expr = default_function_array_conversion (eloc, cmp_expr);
+ }
+ else
+ cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
+ parens.skip_until_found_close (parser);
+ if (cmp_expr.value == error_mark_node)
+ goto saw_error;
+ if (r)
+ {
+ if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
+ goto bad_if;
+ cmp_expr.value = rhs1;
+ rhs1 = NULL_TREE;
+ gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
+ }
+ if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
+ ;
+ else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
+ "expected %<==%> comparison in %<if%> condition");
+ goto saw_error;
+ }
+ else if (TREE_CODE (cmp_expr.value) != GT_EXPR
+ && TREE_CODE (cmp_expr.value) != LT_EXPR)
+ {
+ error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
+ "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
+ "condition");
+ goto saw_error;
+ }
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ goto saw_error;
+
+ extra_scope = true;
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_cast_expression (parser, NULL);
+ lhs = expr.value;
+ expr = default_function_array_conversion (eloc, expr);
+ unfolded_lhs = expr.value;
+ lhs = c_fully_fold (lhs, false, NULL, true);
+ orig_lhs = lhs;
+ if (lhs == error_mark_node)
+ goto saw_error;
+ if (!lvalue_p (unfolded_lhs))
+ lhs = non_lvalue (lhs);
+ if (!c_parser_next_token_is (parser, CPP_EQ))
+ {
+ c_parser_error (parser, "expected %<=%>");
+ goto saw_error;
+ }
+ c_parser_consume_token (parser);
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ rhs1 = expr.value;
+
+ if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ goto saw_error;
+
+ if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+ goto saw_error;
+
+ extra_scope = false;
+ no_semicolon = true;
+
+ if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
+ {
+ if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
+ {
+ opcode = COND_EXPR;
+ rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
+ false, NULL, true);
+ rhs1 = c_fully_fold (rhs1, false, NULL, true);
+ }
+ else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
+ {
+ opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
+ ? MIN_EXPR : MAX_EXPR);
+ rhs = c_fully_fold (rhs1, false, NULL, true);
+ rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
+ false, NULL, true);
+ }
+ else
+ goto bad_if;
+ }
+ else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
+ goto bad_if;
+ else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
+ && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
+ {
+ opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
+ ? MAX_EXPR : MIN_EXPR);
+ rhs = c_fully_fold (rhs1, false, NULL, true);
+ rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
+ false, NULL, true);
+ }
+ else
+ {
+ bad_if:
+ c_parser_error (parser,
+ "invalid form of %<#pragma omp atomic compare%>");
+ goto saw_error;
+ }
+
+ if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+ {
+ if (code != OMP_ATOMIC_CAPTURE_NEW
+ || (structured_block && r == NULL_TREE)
+ || TREE_CODE (cmp_expr.value) != EQ_EXPR)
+ {
+ eloc = c_parser_peek_token (parser)->location;
+ error_at (eloc, "unexpected %<else%>");
+ goto saw_error;
+ }
+
+ c_parser_consume_token (parser);
+
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ goto saw_error;
+
+ extra_scope = true;
+ v = c_parser_cast_expression (parser, NULL).value;
+ non_lvalue_p = !lvalue_p (v);
+ v = c_fully_fold (v, false, NULL, true);
+ if (v == error_mark_node)
+ goto saw_error;
+ if (non_lvalue_p)
+ v = non_lvalue (v);
+ if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+ goto saw_error;
+
+ expr = c_parser_expr_no_commas (parser, NULL);
+
+ if (!c_tree_equal (expr.value, unfolded_lhs))
+ goto bad_if;
+
+ if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ goto saw_error;
+
+ if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+ goto saw_error;
+
+ extra_scope = false;
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ if (r == NULL_TREE)
+ /* Signal to c_finish_omp_atomic that in
+ if (x == e) { x = d; } else { v = x; }
+ case the store to v should be conditional. */
+ r = void_list_node;
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+ {
+ c_parser_require_keyword (parser, RID_ELSE, "expected %<else%>");
+ goto saw_error;
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_NEW
+ && r != NULL_TREE
+ && v == NULL_TREE)
+ code = OMP_ATOMIC;
+ goto stmt_done;
+ }
eloc = c_parser_peek_token (parser)->location;
expr = c_parser_cast_expression (parser, NULL);
lhs = expr.value;
@@ -17653,9 +18236,14 @@ restart:
orig_lhs = lhs;
switch (TREE_CODE (lhs))
{
+ invalid_compare:
+ error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
+ /* FALLTHRU */
case ERROR_MARK:
saw_error:
c_parser_skip_to_end_of_block_or_statement (parser);
+ if (extra_scope && c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ c_parser_consume_token (parser);
if (structured_block)
{
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -17678,6 +18266,8 @@ restart:
unfolded_lhs = NULL_TREE;
opcode = PLUS_EXPR;
rhs = integer_one_node;
+ if (compare)
+ goto invalid_compare;
break;
case POSTDECREMENT_EXPR:
@@ -17689,6 +18279,8 @@ restart:
unfolded_lhs = NULL_TREE;
opcode = MINUS_EXPR;
rhs = integer_one_node;
+ if (compare)
+ goto invalid_compare;
break;
case COMPOUND_EXPR:
@@ -17718,6 +18310,8 @@ restart:
&& !structured_block
&& TREE_CODE (orig_lhs) == COMPOUND_EXPR)
code = OMP_ATOMIC_CAPTURE_OLD;
+ if (compare)
+ goto invalid_compare;
break;
}
if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
@@ -17733,6 +18327,8 @@ restart:
&& !structured_block
&& TREE_CODE (orig_lhs) == COMPOUND_EXPR)
code = OMP_ATOMIC_CAPTURE_OLD;
+ if (compare)
+ goto invalid_compare;
break;
}
}
@@ -17740,6 +18336,11 @@ restart:
default:
if (!lvalue_p (unfolded_lhs))
lhs = non_lvalue (lhs);
+ if (compare && !c_parser_next_token_is (parser, CPP_EQ))
+ {
+ c_parser_error (parser, "expected %<=%>");
+ goto saw_error;
+ }
switch (c_parser_peek_token (parser)->type)
{
case CPP_MULT_EQ:
@@ -17786,6 +18387,8 @@ restart:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
+ if (compare)
+ break;
if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
{
opcode = TREE_CODE (rhs1);
@@ -17806,6 +18409,78 @@ restart:
goto stmt_done;
}
break;
+ case COND_EXPR:
+ if (!compare)
+ break;
+ if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
+ break;
+ if (!TREE_OPERAND (rhs1, 1))
+ break;
+ if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
+ break;
+ if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
+ unfolded_lhs))
+ {
+ if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
+ {
+ opcode = COND_EXPR;
+ rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
+ 0), 1),
+ false, NULL, true);
+ rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
+ NULL, true);
+ goto stmt_done;
+ }
+ if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
+ TREE_OPERAND (rhs1, 1)))
+ {
+ opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
+ ? MIN_EXPR : MAX_EXPR);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+ true);
+ rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
+ 0), 0),
+ false, NULL, true);
+ goto stmt_done;
+ }
+ }
+ else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
+ break;
+ else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
+ unfolded_lhs))
+ {
+ if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
+ TREE_OPERAND (rhs1, 1)))
+ {
+ opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
+ ? MAX_EXPR : MIN_EXPR);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+ true);
+ rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
+ 0), 1),
+ false, NULL, true);
+ goto stmt_done;
+ }
+ }
+ break;
+ case EQ_EXPR:
+ if (!compare
+ || code != OMP_ATOMIC_CAPTURE_NEW
+ || !structured_block
+ || v
+ || r)
+ break;
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+ && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
+ {
+ r = lhs;
+ lhs = NULL_TREE;
+ c_parser_consume_token (parser);
+ goto restart;
+ }
+ break;
case ERROR_MARK:
goto saw_error;
default:
@@ -17854,10 +18529,12 @@ restart:
break;
}
stmt_done:
- if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
{
- if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ if (!no_semicolon
+ && !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
goto saw_error;
+ no_semicolon = false;
v = c_parser_cast_expression (parser, NULL).value;
non_lvalue_p = !lvalue_p (v);
v = c_fully_fold (v, false, NULL, true);
@@ -17880,10 +18557,16 @@ stmt_done:
}
if (structured_block)
{
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ if (!no_semicolon)
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
}
done:
+ if (weak && opcode != COND_EXPR)
+ {
+ error_at (loc, "%<weak%> clause requires atomic equality comparison");
+ weak = false;
+ }
if (unfolded_lhs && unfolded_lhs1
&& !c_tree_equal (unfolded_lhs, unfolded_lhs1))
{
@@ -17892,12 +18575,12 @@ done:
stmt = error_mark_node;
}
else
- stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1,
- swapped, memory_order);
+ stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
+ swapped, memory_order, weak);
if (stmt != error_mark_node)
add_stmt (stmt);
- if (!structured_block)
+ if (!structured_block && !no_semicolon)
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
@@ -18084,7 +18767,9 @@ c_parser_omp_flush (c_parser *parser)
const char *p
= IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (!strcmp (p, "acq_rel"))
+ if (!strcmp (p, "seq_cst"))
+ mo = MEMMODEL_SEQ_CST;
+ else if (!strcmp (p, "acq_rel"))
mo = MEMMODEL_ACQ_REL;
else if (!strcmp (p, "release"))
mo = MEMMODEL_RELEASE;
@@ -18092,7 +18777,8 @@ c_parser_omp_flush (c_parser *parser)
mo = MEMMODEL_ACQUIRE;
else
error_at (c_parser_peek_token (parser)->location,
- "expected %<acq_rel%>, %<release%> or %<acquire%>");
+ "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
+ "%<acquire%>");
c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
@@ -18274,8 +18960,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
vec_safe_push (for_block, c_begin_compound_stmt (true));
this_pre_body = push_stmt_list ();
c_in_omp_for = true;
- c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- NULL, vNULL);
+ c_parser_declaration_or_fndef (parser, true, true, true, true, true);
c_in_omp_for = false;
if (this_pre_body)
{
@@ -18595,7 +19280,9 @@ omp_split_clauses (location_t loc, enum tree_code code,
c_omp_split_clauses (loc, code, mask, clauses, cclauses);
for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
if (cclauses[i])
- cclauses[i] = c_finish_omp_clauses (cclauses[i], C_ORT_OMP);
+ cclauses[i] = c_finish_omp_clauses (cclauses[i],
+ i == C_OMP_CLAUSE_SPLIT_TARGET
+ ? C_ORT_OMP_TARGET : C_ORT_OMP);
}
/* OpenMP 5.0:
@@ -18826,6 +19513,7 @@ c_parser_omp_master (location_t loc, c_parser *parser,
if (ret == NULL_TREE)
return ret;
ret = c_finish_omp_master (loc, block);
+ OMP_MASTER_COMBINED (ret) = 1;
return ret;
}
}
@@ -18847,6 +19535,70 @@ c_parser_omp_master (location_t loc, c_parser *parser,
if_p));
}
+/* OpenMP 5.1:
+ # pragma omp masked masked-clauses new-line
+ structured-block
+
+ LOC is the location of the #pragma token.
+*/
+
+#define OMP_MASKED_CLAUSE_MASK \
+ (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
+
+static tree
+c_parser_omp_masked (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
+{
+ tree block, clauses, ret;
+
+ strcat (p_name, " masked");
+ mask |= OMP_MASKED_CLAUSE_MASK;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ if (strcmp (p, "taskloop") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ c_parser_consume_token (parser);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
+ if_p);
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
+ if_p);
+ block = c_end_compound_stmt (loc, block, true);
+ if (ret == NULL_TREE)
+ return ret;
+ ret = c_finish_omp_masked (loc, block,
+ cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
+ OMP_MASKED_COMBINED (ret) = 1;
+ return ret;
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser, false);
+ return NULL_TREE;
+ }
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_MASKED, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
+ }
+
+ return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
+ if_p),
+ clauses);
+}
+
/* OpenMP 2.5:
# pragma omp ordered new-line
structured-block
@@ -18895,7 +19647,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
"%<#pragma omp ordered%> with %<depend%> clause may "
"only be used in compound statements");
c_parser_skip_to_pragma_eol (parser, false);
- return false;
+ return true;
}
tree clauses
@@ -19109,7 +19861,36 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
else if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (cclauses == NULL && strcmp (p, "master") == 0)
+ if (cclauses == NULL && strcmp (p, "masked") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ cclauses = cclauses_buf;
+
+ c_parser_consume_token (parser);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
+ if_p);
+ block = c_begin_omp_parallel ();
+ tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
+ if_p);
+ stmt = c_finish_omp_parallel (loc,
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ if (ret == NULL)
+ return ret;
+ /* masked does have just filter clause, but during gimplification
+ isn't represented by a gimplification omp context, so for
+ #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
+ so that
+ #pragma omp parallel masked
+ #pragma omp taskloop simd lastprivate (x)
+ isn't confused with
+ #pragma omp parallel masked taskloop simd lastprivate (x) */
+ if (OMP_MASKED_COMBINED (ret))
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
+ }
+ else if (cclauses == NULL && strcmp (p, "master") == 0)
{
tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
cclauses = cclauses_buf;
@@ -19126,7 +19907,16 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
block);
if (ret == NULL)
return ret;
- OMP_PARALLEL_COMBINED (stmt) = 1;
+ /* master doesn't have any clauses and during gimplification
+ isn't represented by a gimplification omp context, so for
+ #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
+ so that
+ #pragma omp parallel master
+ #pragma omp taskloop simd lastprivate (x)
+ isn't confused with
+ #pragma omp parallel master taskloop simd lastprivate (x) */
+ if (OMP_MASTER_COMBINED (ret))
+ OMP_PARALLEL_COMBINED (stmt) = 1;
return stmt;
}
else if (strcmp (p, "loop") == 0)
@@ -19220,6 +20010,33 @@ c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
return add_stmt (stmt);
}
+/* OpenMP 5.1:
+ # pragma omp scope scope-clause[optseq] new-line
+ structured-block
+
+ LOC is the location of the #pragma.
+*/
+
+#define OMP_SCOPE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
+{
+ tree stmt = make_node (OMP_SCOPE);
+ SET_EXPR_LOCATION (stmt, loc);
+ TREE_TYPE (stmt) = void_type_node;
+
+ OMP_SCOPE_CLAUSES (stmt)
+ = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
+ "#pragma omp scope");
+ OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
+
+ return add_stmt (stmt);
+}
+
/* OpenMP 3.0:
# pragma omp task task-clause[optseq] new-line
@@ -19239,7 +20056,8 @@ c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
static tree
c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
@@ -19359,7 +20177,7 @@ c_parser_omp_cancel (c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
-static void
+static bool
c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
{
location_t loc = c_parser_peek_token (parser)->location;
@@ -19380,7 +20198,7 @@ c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
{
c_parser_error (parser, "expected %<point%>");
c_parser_skip_to_pragma_eol (parser);
- return;
+ return false;
}
if (context != pragma_compound)
@@ -19392,7 +20210,7 @@ c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
else
c_parser_error (parser, "expected declaration specifiers");
c_parser_skip_to_pragma_eol (parser, false);
- return;
+ return true;
}
clauses
@@ -19400,6 +20218,7 @@ c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
"#pragma omp cancellation point");
c_finish_omp_cancellation_point (loc, clauses);
+ return true;
}
/* OpenMP 4.0:
@@ -19685,7 +20504,7 @@ c_parser_omp_target_update (location_t loc, c_parser *parser,
error_at (loc, "%<#pragma %s%> may only be used in compound statements",
"omp target update");
c_parser_skip_to_pragma_eol (parser, false);
- return false;
+ return true;
}
tree clauses
@@ -19718,7 +20537,7 @@ c_parser_omp_target_update (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-static tree
+static bool
c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
enum pragma_context context)
{
@@ -19736,7 +20555,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
{
c_parser_error (parser, "expected %<data%>");
c_parser_skip_to_pragma_eol (parser);
- return NULL_TREE;
+ return false;
}
if (context == pragma_stmt)
@@ -19744,7 +20563,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
error_at (loc, "%<#pragma %s%> may only be used in compound statements",
"omp target enter data");
c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
+ return true;
}
tree clauses
@@ -19783,7 +20602,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
error_at (loc,
"%<#pragma omp target enter data%> must contain at least "
"one %<map%> clause");
- return NULL_TREE;
+ return true;
}
tree stmt = make_node (OMP_TARGET_ENTER_DATA);
@@ -19791,7 +20610,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
SET_EXPR_LOCATION (stmt, loc);
add_stmt (stmt);
- return stmt;
+ return true;
}
/* OpenMP 4.5:
@@ -19804,7 +20623,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-static tree
+static bool
c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
enum pragma_context context)
{
@@ -19822,7 +20641,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
{
c_parser_error (parser, "expected %<data%>");
c_parser_skip_to_pragma_eol (parser);
- return NULL_TREE;
+ return false;
}
if (context == pragma_stmt)
@@ -19830,7 +20649,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
error_at (loc, "%<#pragma %s%> may only be used in compound statements",
"omp target exit data");
c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
+ return true;
}
tree clauses
@@ -19871,7 +20690,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
error_at (loc,
"%<#pragma omp target exit data%> must contain at least one "
"%<map%> clause");
- return NULL_TREE;
+ return true;
}
tree stmt = make_node (OMP_TARGET_EXIT_DATA);
@@ -19879,7 +20698,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
SET_EXPR_LOCATION (stmt, loc);
add_stmt (stmt);
- return stmt;
+ return true;
}
/* OpenMP 4.0:
@@ -19896,6 +20715,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
static bool
@@ -20014,6 +20834,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
tree stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
+ c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
OMP_TARGET_BODY (stmt) = block;
OMP_TARGET_COMBINED (stmt) = 1;
SET_EXPR_LOCATION (stmt, loc);
@@ -20035,14 +20856,12 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
else if (strcmp (p, "enter") == 0)
{
c_parser_consume_token (parser);
- c_parser_omp_target_enter_data (loc, parser, context);
- return false;
+ return c_parser_omp_target_enter_data (loc, parser, context);
}
else if (strcmp (p, "exit") == 0)
{
c_parser_consume_token (parser);
- c_parser_omp_target_exit_data (loc, parser, context);
- return false;
+ return c_parser_omp_target_exit_data (loc, parser, context);
}
else if (strcmp (p, "update") == 0)
{
@@ -20061,7 +20880,18 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
OMP_TARGET_CLAUSES (stmt)
= c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
- "#pragma omp target");
+ "#pragma omp target", false);
+ for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
+ {
+ tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
+ OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
+ OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
+ OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = nc;
+ }
+ OMP_TARGET_CLAUSES (stmt)
+ = c_finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET);
c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
pc = &OMP_TARGET_CLAUSES (stmt);
@@ -20190,12 +21020,12 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
while (c_parser_next_token_is (parser, CPP_KEYWORD)
&& c_parser_peek_token (parser)->keyword == RID_EXTENSION);
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, clauses);
+ NULL, &clauses);
restore_extension_diagnostics (ext);
}
else
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, clauses);
+ NULL, &clauses);
break;
case pragma_struct:
case pragma_param:
@@ -20216,7 +21046,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, clauses);
+ true, NULL, &clauses);
restore_extension_diagnostics (ext);
break;
}
@@ -20225,7 +21055,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
else if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- NULL, clauses);
+ NULL, &clauses);
break;
}
error ("%<#pragma omp declare %s%> must be followed by "
@@ -20706,8 +21536,10 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
static void
c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
- vec<c_token> clauses)
+ vec<c_token> *pclauses)
{
+ vec<c_token> &clauses = *pclauses;
+
/* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
indicates error has been reported and CPP_PRAGMA that
c_finish_omp_declare_simd has already processed the tokens. */
@@ -21288,7 +22120,7 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
OpenMP 5.0
#pragma omp declare variant (identifier) match (context-selector) */
-static void
+static bool
c_parser_omp_declare (c_parser *parser, enum pragma_context context)
{
c_parser_consume_pragma (parser);
@@ -21300,37 +22132,38 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
/* c_parser_consume_token (parser); done in
c_parser_omp_declare_simd. */
c_parser_omp_declare_simd (parser, context);
- return;
+ return true;
}
if (strcmp (p, "reduction") == 0)
{
c_parser_consume_token (parser);
c_parser_omp_declare_reduction (parser, context);
- return;
+ return false;
}
if (!flag_openmp) /* flag_openmp_simd */
{
c_parser_skip_to_pragma_eol (parser, false);
- return;
+ return false;
}
if (strcmp (p, "target") == 0)
{
c_parser_consume_token (parser);
c_parser_omp_declare_target (parser);
- return;
+ return false;
}
if (strcmp (p, "variant") == 0)
{
/* c_parser_consume_token (parser); done in
c_parser_omp_declare_simd. */
c_parser_omp_declare_simd (parser, context);
- return;
+ return true;
}
}
c_parser_error (parser, "expected %<simd%>, %<reduction%>, "
"%<target%> or %<variant%>");
c_parser_skip_to_pragma_eol (parser);
+ return false;
}
/* OpenMP 5.0
@@ -21347,7 +22180,9 @@ c_parser_omp_requires (c_parser *parser)
location_t loc = c_parser_peek_token (parser)->location;
while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
{
- if (!first && c_parser_next_token_is (parser, CPP_COMMA))
+ if (!first
+ && c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
c_parser_consume_token (parser);
first = false;
@@ -21394,9 +22229,18 @@ c_parser_omp_requires (c_parser *parser)
error_at (c_parser_peek_token (parser)->location,
"expected %<seq_cst%>, %<relaxed%> or "
"%<acq_rel%>");
- if (c_parser_peek_2nd_token (parser)->type
- == CPP_CLOSE_PAREN)
- c_parser_consume_token (parser);
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_EOF:
+ case CPP_PRAGMA_EOL:
+ case CPP_CLOSE_PAREN:
+ break;
+ default:
+ if (c_parser_peek_2nd_token (parser)->type
+ == CPP_CLOSE_PAREN)
+ c_parser_consume_token (parser);
+ break;
+ }
}
else
c_parser_consume_token (parser);
@@ -21597,6 +22441,183 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
return ret;
}
+/* OpenMP 5.1
+ #pragma omp nothing new-line */
+
+static void
+c_parser_omp_nothing (c_parser *parser)
+{
+ c_parser_consume_pragma (parser);
+ c_parser_skip_to_pragma_eol (parser);
+}
+
+/* OpenMP 5.1
+ #pragma omp error clauses[optseq] new-line */
+
+static bool
+c_parser_omp_error (c_parser *parser, enum pragma_context context)
+{
+ int at_compilation = -1;
+ int severity_fatal = -1;
+ tree message = NULL_TREE;
+ bool first = true;
+ bool bad = false;
+ location_t loc = c_parser_peek_token (parser)->location;
+
+ c_parser_consume_pragma (parser);
+
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ if (!first
+ && c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+ c_parser_consume_token (parser);
+
+ first = false;
+
+ if (!c_parser_next_token_is (parser, CPP_NAME))
+ break;
+
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ location_t cloc = c_parser_peek_token (parser)->location;
+ static const char *args[] = {
+ "execution", "compilation", "warning", "fatal"
+ };
+ int *v = NULL;
+ int idx = 0, n = -1;
+ tree m = NULL_TREE;
+
+ if (!strcmp (p, "at"))
+ v = &at_compilation;
+ else if (!strcmp (p, "severity"))
+ {
+ v = &severity_fatal;
+ idx += 2;
+ }
+ else if (strcmp (p, "message"))
+ {
+ error_at (cloc,
+ "expected %<at%>, %<severity%> or %<message%> clause");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return false;
+ }
+
+ c_parser_consume_token (parser);
+
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ if (v == NULL)
+ {
+ 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, true, true);
+ m = convert (const_string_type_node, expr.value);
+ m = c_fully_fold (m, false, NULL);
+ }
+ else
+ {
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ tree val = c_parser_peek_token (parser)->value;
+ const char *q = IDENTIFIER_POINTER (val);
+
+ if (!strcmp (q, args[idx]))
+ n = 0;
+ else if (!strcmp (q, args[idx + 1]))
+ n = 1;
+ }
+ if (n == -1)
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "expected %qs or %qs", args[idx], args[idx + 1]);
+ bad = true;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_EOF:
+ case CPP_PRAGMA_EOL:
+ case CPP_CLOSE_PAREN:
+ break;
+ default:
+ if (c_parser_peek_2nd_token (parser)->type
+ == CPP_CLOSE_PAREN)
+ c_parser_consume_token (parser);
+ break;
+ }
+ }
+ else
+ c_parser_consume_token (parser);
+ }
+
+ parens.skip_until_found_close (parser);
+
+ if (v == NULL)
+ {
+ if (message)
+ {
+ error_at (cloc, "too many %qs clauses", p);
+ bad = true;
+ }
+ else
+ message = m;
+ }
+ else if (n != -1)
+ {
+ if (*v != -1)
+ {
+ error_at (cloc, "too many %qs clauses", p);
+ bad = true;
+ }
+ else
+ *v = n;
+ }
+ }
+ else
+ bad = true;
+ }
+ c_parser_skip_to_pragma_eol (parser);
+ if (bad)
+ return true;
+
+ if (at_compilation == -1)
+ at_compilation = 1;
+ if (severity_fatal == -1)
+ severity_fatal = 1;
+ if (!at_compilation)
+ {
+ if (context != pragma_compound)
+ {
+ error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
+ "may only be used in compound statements");
+ return true;
+ }
+ tree fndecl
+ = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR
+ : BUILT_IN_GOMP_WARNING);
+ if (!message)
+ message = build_zero_cst (const_string_type_node);
+ tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
+ build_all_ones_cst (size_type_node));
+ add_stmt (stmt);
+ return true;
+ }
+ const char *msg = NULL;
+ if (message)
+ {
+ msg = c_getstr (message);
+ if (msg == NULL)
+ msg = _("<message unknown at compile time>");
+ }
+ if (msg)
+ emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
+ "%<pragma omp error%> encountered: %s", msg);
+ else
+ emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
+ "%<pragma omp error%> encountered");
+ return false;
+}
+
/* Main entry point to parsing most OpenMP pragmas. */
static void
@@ -21662,6 +22683,10 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
strcpy (p_name, "#pragma omp");
stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
break;
+ case PRAGMA_OMP_MASKED:
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
+ break;
case PRAGMA_OMP_MASTER:
strcpy (p_name, "#pragma omp");
stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
@@ -21670,6 +22695,9 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
strcpy (p_name, "#pragma omp");
stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
break;
+ case PRAGMA_OMP_SCOPE:
+ stmt = c_parser_omp_scope (loc, parser, if_p);
+ break;
case PRAGMA_OMP_SECTIONS:
strcpy (p_name, "#pragma omp");
stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index a671a3e..d50d0cb 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -370,6 +370,8 @@ struct c_declspecs {
BOOL_BITFIELD explicit_signed_p : 1;
/* Whether the specifiers include a deprecated typedef. */
BOOL_BITFIELD deprecated_p : 1;
+ /* Whether the specifiers include an unavailable typedef. */
+ BOOL_BITFIELD unavailable_p : 1;
/* Whether the type defaulted to "int" because there were no type
specifiers. */
BOOL_BITFIELD default_int_p : 1;
@@ -595,7 +597,7 @@ extern void finish_function (location_t = input_location);
extern tree finish_struct (location_t, tree, tree, tree,
class c_struct_parse_info *);
extern tree c_simulate_enum_decl (location_t, const char *,
- vec<string_int_pair>);
+ vec<string_int_pair> *);
extern struct c_arg_info *build_arg_info (void);
extern struct c_arg_info *get_parm_info (bool, tree);
extern tree grokfield (location_t, struct c_declarator *,
@@ -759,8 +761,9 @@ extern tree c_finish_omp_clauses (tree, enum c_omp_region_type);
extern tree c_build_va_arg (location_t, tree, location_t, tree);
extern tree c_finish_transaction (location_t, tree, int);
extern bool c_tree_equal (tree, tree);
-extern tree c_build_function_call_vec (location_t, vec<location_t>, tree,
- vec<tree, va_gc> *, vec<tree, va_gc> *);
+extern tree c_build_function_call_vec (location_t, const vec<location_t>&,
+ tree, vec<tree, va_gc> *,
+ vec<tree, va_gc> *);
extern tree c_omp_clause_copy_ctor (tree, tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 4e6d369..49d1bb0 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -740,10 +740,16 @@ c_common_type (tree t1, tree t2)
t2 = TYPE_MAIN_VARIANT (t2);
if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
- t1 = build_type_attribute_variant (t1, NULL_TREE);
+ {
+ tree attrs = affects_type_identity_attributes (TYPE_ATTRIBUTES (t1));
+ t1 = build_type_attribute_variant (t1, attrs);
+ }
if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
- t2 = build_type_attribute_variant (t2, NULL_TREE);
+ {
+ tree attrs = affects_type_identity_attributes (TYPE_ATTRIBUTES (t2));
+ t2 = build_type_attribute_variant (t2, attrs);
+ }
/* Save time if the two types are the same. */
@@ -1322,8 +1328,8 @@ comp_target_types (location_t location, tree ttl, tree ttr)
val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
if (val == 1 && val_ped != 1)
- pedwarn (location, OPT_Wpedantic, "pointers to arrays with different qualifiers "
- "are incompatible in ISO C");
+ pedwarn_c11 (location, OPT_Wpedantic, "invalid use of pointers to arrays with different qualifiers "
+ "in ISO C before C2X");
if (val == 2)
pedwarn (location, OPT_Wpedantic, "types are not quite compatible");
@@ -1686,7 +1692,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
if (args1 == NULL_TREE)
{
- if (!self_promoting_args_p (args2))
+ if (flag_isoc2x ? stdarg_p (f2) : !self_promoting_args_p (args2))
return 0;
/* If one of these types comes from a non-prototype fn definition,
compare that with the other type's arglist.
@@ -1699,7 +1705,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
}
if (args2 == NULL_TREE)
{
- if (!self_promoting_args_p (args1))
+ if (flag_isoc2x ? stdarg_p (f1) : !self_promoting_args_p (args1))
return 0;
if (TYPE_ACTUAL_ARG_TYPES (f2)
&& type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
@@ -1905,8 +1911,7 @@ array_to_pointer_conversion (location_t loc, tree exp)
STRIP_TYPE_NOPS (exp);
- if (TREE_NO_WARNING (orig_exp))
- TREE_NO_WARNING (exp) = 1;
+ copy_warning (exp, orig_exp);
ptrtype = build_pointer_type (restype);
@@ -1939,8 +1944,7 @@ function_to_pointer_conversion (location_t loc, tree exp)
STRIP_TYPE_NOPS (exp);
- if (TREE_NO_WARNING (orig_exp))
- TREE_NO_WARNING (exp) = 1;
+ copy_warning (exp, orig_exp);
return build_unary_op (loc, ADDR_EXPR, exp, false);
}
@@ -1968,6 +1972,50 @@ mark_exp_read (tree exp)
mark_exp_read (TREE_OPERAND (exp, 0));
break;
case COMPOUND_EXPR:
+ /* Pattern match what build_atomic_assign produces with modifycode
+ NOP_EXPR. */
+ if (VAR_P (TREE_OPERAND (exp, 1))
+ && DECL_ARTIFICIAL (TREE_OPERAND (exp, 1))
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == COMPOUND_EXPR)
+ {
+ tree t1 = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree t2 = TREE_OPERAND (TREE_OPERAND (exp, 0), 1);
+ if (TREE_CODE (t1) == TARGET_EXPR
+ && TARGET_EXPR_SLOT (t1) == TREE_OPERAND (exp, 1)
+ && TREE_CODE (t2) == CALL_EXPR)
+ {
+ tree fndecl = get_callee_fndecl (t2);
+ tree arg = NULL_TREE;
+ if (fndecl
+ && TREE_CODE (fndecl) == FUNCTION_DECL
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
+ && call_expr_nargs (t2) >= 2)
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_ATOMIC_STORE:
+ arg = CALL_EXPR_ARG (t2, 1);
+ break;
+ case BUILT_IN_ATOMIC_STORE_1:
+ case BUILT_IN_ATOMIC_STORE_2:
+ case BUILT_IN_ATOMIC_STORE_4:
+ case BUILT_IN_ATOMIC_STORE_8:
+ case BUILT_IN_ATOMIC_STORE_16:
+ arg = CALL_EXPR_ARG (t2, 0);
+ break;
+ default:
+ break;
+ }
+ if (arg)
+ {
+ STRIP_NOPS (arg);
+ if (TREE_CODE (arg) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (arg, 0))
+ && TYPE_ATOMIC (TREE_TYPE (TREE_OPERAND (arg, 0))))
+ mark_exp_read (TREE_OPERAND (arg, 0));
+ }
+ }
+ }
+ /* FALLTHRU */
case C_MAYBE_CONST_EXPR:
mark_exp_read (TREE_OPERAND (exp, 1));
break;
@@ -2005,8 +2053,7 @@ default_function_array_conversion (location_t loc, struct c_expr exp)
exp.value = TREE_OPERAND (exp.value, 0);
}
- if (TREE_NO_WARNING (orig_exp))
- TREE_NO_WARNING (exp.value) = 1;
+ copy_warning (exp.value, orig_exp);
lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
if (!flag_isoc99 && !lvalue_array_p)
@@ -2104,7 +2151,8 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
tmp = create_tmp_var_raw (nonatomic_type);
tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, false);
TREE_ADDRESSABLE (tmp) = 1;
- TREE_NO_WARNING (tmp) = 1;
+ /* Do not disable warnings for TMP even though it's artificial.
+ -Winvalid-memory-model depends on it. */
/* Issue __atomic_load (&expr, &tmp, SEQ_CST); */
fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
@@ -2201,8 +2249,7 @@ default_conversion (tree exp)
orig_exp = exp;
STRIP_TYPE_NOPS (exp);
- if (TREE_NO_WARNING (orig_exp))
- TREE_NO_WARNING (exp) = 1;
+ copy_warning (exp, orig_exp);
if (code == VOID_TYPE)
{
@@ -2511,7 +2558,9 @@ build_component_ref (location_t loc, tree datum, tree component,
|| (use_datum_quals && TREE_THIS_VOLATILE (datum)))
TREE_THIS_VOLATILE (ref) = 1;
- if (TREE_DEPRECATED (subdatum))
+ if (TREE_UNAVAILABLE (subdatum))
+ error_unavailable_use (subdatum, NULL_TREE);
+ else if (TREE_DEPRECATED (subdatum))
warn_deprecated_use (subdatum, NULL_TREE);
datum = ref;
@@ -2566,7 +2615,7 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
if (warn_strict_aliasing > 2)
if (strict_aliasing_warning (EXPR_LOCATION (pointer),
type, TREE_OPERAND (pointer, 0)))
- TREE_NO_WARNING (pointer) = 1;
+ suppress_warning (pointer, OPT_Wstrict_aliasing_);
}
if (TREE_CODE (pointer) == ADDR_EXPR
@@ -2796,7 +2845,9 @@ build_external_ref (location_t loc, tree id, bool fun, tree *type)
if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node;
- if (TREE_DEPRECATED (ref))
+ if (TREE_UNAVAILABLE (ref))
+ error_unavailable_use (ref, NULL_TREE);
+ else if (TREE_DEPRECATED (ref))
warn_deprecated_use (ref, NULL_TREE);
/* Recursive call does not count as usage. */
@@ -2945,7 +2996,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr)
c_last_sizeof_loc = loc;
ret.original_code = SIZEOF_EXPR;
ret.original_type = NULL;
- if (c_vla_type_p (TREE_TYPE (folded_expr)))
+ if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (folded_expr)))
{
/* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */
ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
@@ -2975,8 +3026,14 @@ c_expr_sizeof_type (location_t loc, struct c_type_name *t)
c_last_sizeof_loc = loc;
ret.original_code = SIZEOF_EXPR;
ret.original_type = NULL;
+ if (type == error_mark_node)
+ {
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ }
+ else
if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
- && c_vla_type_p (type))
+ && C_TYPE_VARIABLE_SIZE (type))
{
/* If the type is a [*] array, it is a VLA but is represented as
having a size of zero. In such a case we must ensure that
@@ -3063,7 +3120,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
orig_fundecl = fundecl;
/* Atomic functions have type checking/casting already done. They are
often rewritten and don't match the original parameter list. */
- if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
+ if (name && startswith (IDENTIFIER_POINTER (name), "__atomic_"))
origtypes = NULL;
}
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
@@ -3149,7 +3206,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
nargs, argarray, &arg_loc);
if (name != NULL_TREE
- && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
+ && startswith (IDENTIFIER_POINTER (name), "__builtin_"))
{
if (require_constant_value)
result
@@ -3168,7 +3225,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
/* If -Wnonnull warning has been diagnosed, avoid diagnosing it again
later. */
if (warned_p && TREE_CODE (result) == CALL_EXPR)
- TREE_NO_WARNING (result) = 1;
+ suppress_warning (result, OPT_Wnonnull);
/* In this improbable scenario, a nested function returns a VM type.
Create a TARGET_EXPR so that the call always has a LHS, much as
@@ -3193,7 +3250,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
/* Like build_function_call_vec, but call also resolve_overloaded_builtin. */
tree
-c_build_function_call_vec (location_t loc, vec<location_t> arg_loc,
+c_build_function_call_vec (location_t loc, const vec<location_t> &arg_loc,
tree function, vec<tree, va_gc> *params,
vec<tree, va_gc> *origtypes)
{
@@ -4065,7 +4122,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
vec<tree, va_gc> *params;
tree val, nonatomic_lhs_type, nonatomic_rhs_type, newval, newval_addr;
tree old, old_addr;
- tree compound_stmt;
+ tree compound_stmt = NULL_TREE;
tree stmt, goto_stmt;
tree loop_label, loop_decl, done_label, done_decl;
@@ -4086,7 +4143,15 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
/* Create a compound statement to hold the sequence of statements
with a loop. */
- compound_stmt = c_begin_compound_stmt (false);
+ if (modifycode != NOP_EXPR)
+ {
+ compound_stmt = c_begin_compound_stmt (false);
+
+ /* For consistency with build_modify_expr on non-_Atomic,
+ mark the lhs as read. Also, it would be very hard to match
+ such expressions in mark_exp_read. */
+ mark_exp_read (lhs);
+ }
/* Remove any excess precision (which is only present here in the
case of compound assignments). */
@@ -4109,16 +4174,19 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
TYPE_UNQUALIFIED);
val = create_tmp_var_raw (nonatomic_rhs_type);
TREE_ADDRESSABLE (val) = 1;
- TREE_NO_WARNING (val) = 1;
+ suppress_warning (val);
rhs = build4 (TARGET_EXPR, nonatomic_rhs_type, val, rhs, NULL_TREE,
NULL_TREE);
+ TREE_SIDE_EFFECTS (rhs) = 1;
SET_EXPR_LOCATION (rhs, loc);
- add_stmt (rhs);
+ if (modifycode != NOP_EXPR)
+ add_stmt (rhs);
/* NOP_EXPR indicates it's a straight store of the RHS. Simply issue
an atomic_store. */
if (modifycode == NOP_EXPR)
{
+ compound_stmt = rhs;
/* Build __atomic_store (&lhs, &val, SEQ_CST) */
rhs = build_unary_op (loc, ADDR_EXPR, val, false);
fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_STORE);
@@ -4126,10 +4194,9 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
params->quick_push (rhs);
params->quick_push (seq_cst);
func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
- add_stmt (func_call);
- /* Finish the compound statement. */
- compound_stmt = c_end_compound_stmt (loc, compound_stmt, false);
+ compound_stmt = build2 (COMPOUND_EXPR, void_type_node,
+ compound_stmt, func_call);
/* VAL is the value which was stored, return a COMPOUND_STMT of
the statement and that value. */
@@ -4208,7 +4275,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
newval = create_tmp_var_raw (nonatomic_lhs_type);
TREE_ADDRESSABLE (newval) = 1;
- TREE_NO_WARNING (newval) = 1;
+ suppress_warning (newval);
rhs = build4 (TARGET_EXPR, nonatomic_lhs_type, newval, func_call,
NULL_TREE, NULL_TREE);
SET_EXPR_LOCATION (rhs, loc);
@@ -4227,12 +4294,12 @@ cas_loop:
old = create_tmp_var_raw (nonatomic_lhs_type);
old_addr = build_unary_op (loc, ADDR_EXPR, old, false);
TREE_ADDRESSABLE (old) = 1;
- TREE_NO_WARNING (old) = 1;
+ suppress_warning (old);
newval = create_tmp_var_raw (nonatomic_lhs_type);
newval_addr = build_unary_op (loc, ADDR_EXPR, newval, false);
TREE_ADDRESSABLE (newval) = 1;
- TREE_NO_WARNING (newval) = 1;
+ suppress_warning (newval);
loop_decl = create_artificial_label (loc);
loop_label = build1 (LABEL_EXPR, void_type_node, loop_decl);
@@ -4721,8 +4788,6 @@ 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 (TREE_CODE (val) != code)
- TREE_NO_WARNING (val) = 1;
ret = val;
goto return_build_unary_op;
}
@@ -4806,6 +4871,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (arg, 0))))
{
if (!AGGREGATE_TYPE_P (TREE_TYPE (arg))
+ && !POINTER_TYPE_P (TREE_TYPE (arg))
&& !VECTOR_TYPE_P (TREE_TYPE (arg)))
{
error_at (location, "cannot take address of scalar with "
@@ -4973,8 +5039,17 @@ c_mark_addressable (tree exp, bool array_ref_p)
&& TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
return true;
- /* FALLTHRU */
+ x = TREE_OPERAND (x, 0);
+ break;
+
case COMPONENT_REF:
+ if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
+ {
+ error ("cannot take address of bit-field %qD",
+ TREE_OPERAND (x, 1));
+ return false;
+ }
+ /* FALLTHRU */
case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
@@ -5335,39 +5410,41 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
"used in conditional expression");
return error_mark_node;
}
- else if (VOID_TYPE_P (TREE_TYPE (type1))
- && !TYPE_ATOMIC (TREE_TYPE (type1)))
- {
- if ((TREE_CODE (TREE_TYPE (type2)) == ARRAY_TYPE)
- && (TYPE_QUALS (strip_array_types (TREE_TYPE (type2)))
- & ~TYPE_QUALS (TREE_TYPE (type1))))
- warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
- "pointer to array loses qualifier "
- "in conditional expression");
-
- if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
+ else if ((VOID_TYPE_P (TREE_TYPE (type1))
+ && !TYPE_ATOMIC (TREE_TYPE (type1)))
+ || (VOID_TYPE_P (TREE_TYPE (type2))
+ && !TYPE_ATOMIC (TREE_TYPE (type2))))
+ {
+ tree t1 = TREE_TYPE (type1);
+ tree t2 = TREE_TYPE (type2);
+ if (!(VOID_TYPE_P (t1)
+ && !TYPE_ATOMIC (t1)))
+ {
+ /* roles are swapped */
+ t1 = t2;
+ t2 = TREE_TYPE (type1);
+ }
+ tree t2_stripped = strip_array_types (t2);
+ if ((TREE_CODE (t2) == ARRAY_TYPE)
+ && (TYPE_QUALS (t2_stripped) & ~TYPE_QUALS (t1)))
+ {
+ if (!flag_isoc2x)
+ warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
+ "pointer to array loses qualifier "
+ "in conditional expression");
+ else if (warn_c11_c2x_compat > 0)
+ warning_at (colon_loc, OPT_Wc11_c2x_compat,
+ "pointer to array loses qualifier "
+ "in conditional expression in ISO C before C2X");
+ }
+ if (TREE_CODE (t2) == FUNCTION_TYPE)
pedwarn (colon_loc, OPT_Wpedantic,
"ISO C forbids conditional expr between "
"%<void *%> and function pointer");
- result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
- TREE_TYPE (type2)));
- }
- else if (VOID_TYPE_P (TREE_TYPE (type2))
- && !TYPE_ATOMIC (TREE_TYPE (type2)))
- {
- if ((TREE_CODE (TREE_TYPE (type1)) == ARRAY_TYPE)
- && (TYPE_QUALS (strip_array_types (TREE_TYPE (type1)))
- & ~TYPE_QUALS (TREE_TYPE (type2))))
- warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
- "pointer to array loses qualifier "
- "in conditional expression");
-
- if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
- pedwarn (colon_loc, OPT_Wpedantic,
- "ISO C forbids conditional expr between "
- "%<void *%> and function pointer");
- result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
- TREE_TYPE (type1)));
+ /* for array, use qualifiers of element type */
+ if (flag_isoc2x)
+ t2 = t2_stripped;
+ result_type = build_pointer_type (qualify_type (t1, t2));
}
/* Objective-C pointer comparisons are a bit more lenient. */
else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
@@ -5490,7 +5567,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
warn here, because the COND_EXPR will be turned into OP1. */
if (warn_duplicated_branches
&& TREE_CODE (ret) == COND_EXPR
- && (op1 == op2 || operand_equal_p (op1, op2, 0)))
+ && (op1 == op2 || operand_equal_p (op1, op2, OEP_ADDRESS_OF_SAME_FIELD)))
warning_at (EXPR_LOCATION (ret), OPT_Wduplicated_branches,
"this condition has identical branches");
@@ -6061,6 +6138,7 @@ build_c_cast (location_t loc, tree type, tree expr)
return value reflects this. */
if (int_operands
&& INTEGRAL_TYPE_P (type)
+ && value != error_mark_node
&& !EXPR_INT_CONST_OPERANDS (value))
value = note_integer_operands (value);
@@ -6725,27 +6803,40 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
/* This macro is used to emit diagnostics to ensure that all format
strings are complete sentences, visible to gettext and checked at
- compile time. It is the same as PEDWARN_FOR_ASSIGNMENT but with an
- extra parameter to enumerate qualifiers. */
-#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+ compile time. It can be called with 'pedwarn' or 'warning_at'. */
+#define WARNING_FOR_QUALIFIERS(PEDWARN, LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- { \
- auto_diagnostic_group d; \
- if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
- } \
+ { \
+ auto_diagnostic_group d; \
+ if (PEDWARN) { \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } else { \
+ if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } \
+ } \
break; \
case ic_assign: \
- pedwarn (LOCATION, OPT, AS, QUALS); \
+ if (PEDWARN) \
+ pedwarn (LOCATION, OPT, AS, QUALS); \
+ else \
+ warning_at (LOCATION, OPT, AS, QUALS); \
break; \
case ic_init: \
- pedwarn (LOCATION, OPT, IN, QUALS); \
+ if (PEDWARN) \
+ pedwarn (LOCATION, OPT, IN, QUALS); \
+ else \
+ warning_at (LOCATION, OPT, IN, QUALS); \
break; \
case ic_return: \
- pedwarn (LOCATION, OPT, RE, QUALS); \
+ if (PEDWARN) \
+ pedwarn (LOCATION, OPT, RE, QUALS); \
+ else \
+ warning_at (LOCATION, OPT, RE, QUALS); \
break; \
default: \
gcc_unreachable (); \
@@ -6754,32 +6845,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
/* This macro is used to emit diagnostics to ensure that all format
strings are complete sentences, visible to gettext and checked at
- compile time. It is the same as PEDWARN_FOR_QUALIFIERS but uses
- warning_at instead of pedwarn. */
-#define WARNING_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
- do { \
- switch (errtype) \
- { \
- case ic_argpass: \
- { \
- auto_diagnostic_group d; \
- if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
- } \
- break; \
- case ic_assign: \
- warning_at (LOCATION, OPT, AS, QUALS); \
- break; \
- case ic_init: \
- warning_at (LOCATION, OPT, IN, QUALS); \
- break; \
- case ic_return: \
- warning_at (LOCATION, OPT, RE, QUALS); \
- break; \
- default: \
- gcc_unreachable (); \
- } \
- } while (0)
+ compile time. It is the same as PEDWARN_FOR_ASSIGNMENT but with an
+ extra parameter to enumerate qualifiers. */
+#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+ WARNING_FOR_QUALIFIERS (true, LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS)
+
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
rhs = TREE_OPERAND (rhs, 0);
@@ -7234,26 +7304,37 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
&& (AGGREGATE_TYPE_P (ttl) && TYPE_REVERSE_STORAGE_ORDER (ttl))
!= (AGGREGATE_TYPE_P (ttr) && TYPE_REVERSE_STORAGE_ORDER (ttr)))
{
+ tree t;
+
switch (errtype)
{
case ic_argpass:
/* Do not warn for built-in functions, for example memcpy, since we
control how they behave and they can be useful in this area. */
if (TREE_CODE (rname) != FUNCTION_DECL
- || !DECL_IS_UNDECLARED_BUILTIN (rname))
+ || !fndecl_built_in_p (rname))
warning_at (location, OPT_Wscalar_storage_order,
"passing argument %d of %qE from incompatible "
"scalar storage order", parmnum, rname);
break;
case ic_assign:
- warning_at (location, OPT_Wscalar_storage_order,
- "assignment to %qT from pointer type %qT with "
- "incompatible scalar storage order", type, rhstype);
+ /* Do not warn if the RHS is a call to a function that returns a
+ pointer that is not an alias. */
+ if (TREE_CODE (rhs) != CALL_EXPR
+ || (t = get_callee_fndecl (rhs)) == NULL_TREE
+ || !DECL_IS_MALLOC (t))
+ warning_at (location, OPT_Wscalar_storage_order,
+ "assignment to %qT from pointer type %qT with "
+ "incompatible scalar storage order", type, rhstype);
break;
case ic_init:
- warning_at (location, OPT_Wscalar_storage_order,
- "initialization of %qT from pointer type %qT with "
- "incompatible scalar storage order", type, rhstype);
+ /* Likewise. */
+ if (TREE_CODE (rhs) != CALL_EXPR
+ || (t = get_callee_fndecl (rhs)) == NULL_TREE
+ || !DECL_IS_MALLOC (t))
+ warning_at (location, OPT_Wscalar_storage_order,
+ "initialization of %qT from pointer type %qT with "
+ "incompatible scalar storage order", type, rhstype);
break;
case ic_return:
warning_at (location, OPT_Wscalar_storage_order,
@@ -7287,17 +7368,18 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
- WARNING_FOR_QUALIFIERS (location, expr_loc,
- OPT_Wdiscarded_array_qualifiers,
- G_("passing argument %d of %qE discards "
+ WARNING_FOR_QUALIFIERS (flag_isoc2x,
+ location, expr_loc,
+ OPT_Wdiscarded_array_qualifiers,
+ G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
- G_("assignment discards %qv qualifier "
+ G_("assignment discards %qv qualifier "
"from pointer target type"),
- G_("initialization discards %qv qualifier "
+ G_("initialization discards %qv qualifier "
"from pointer target type"),
- G_("return discards %qv qualifier from "
+ G_("return discards %qv qualifier from "
"pointer target type"),
- TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+ TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
}
else if (pedantic
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -7320,28 +7402,31 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
+ /* Assignments between atomic and non-atomic objects are OK. */
+ bool warn_quals_ped = TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
+ & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl);
+ bool warn_quals = TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
+ & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (strip_array_types (ttl));
+
/* Don't warn about loss of qualifier for conversions from
qualified void* to pointers to arrays with corresponding
- qualifier on the element type. */
- if (!pedantic)
- ttl = strip_array_types (ttl);
+ qualifier on the element type (except for pedantic before C23). */
+ if (warn_quals || (warn_quals_ped && pedantic && !flag_isoc2x))
+ PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
+ G_("passing argument %d of %qE discards "
+ "%qv qualifier from pointer target type"),
+ G_("assignment discards %qv qualifier "
+ "from pointer target type"),
+ G_("initialization discards %qv qualifier "
+ "from pointer target type"),
+ G_("return discards %qv qualifier from "
+ "pointer target type"),
+ TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+ else if (warn_quals_ped)
+ pedwarn_c11 (location, OPT_Wc11_c2x_compat,
+ "array with qualifier on the element is not qualified before C2X");
- /* Assignments between atomic and non-atomic objects are OK. */
- if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
- & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
- {
- PEDWARN_FOR_QUALIFIERS (location, expr_loc,
- OPT_Wdiscarded_qualifiers,
- G_("passing argument %d of %qE discards "
- "%qv qualifier from pointer target type"),
- G_("assignment discards %qv qualifier "
- "from pointer target type"),
- G_("initialization discards %qv qualifier "
- "from pointer target type"),
- G_("return discards %qv qualifier from "
- "pointer target type"),
- TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
- }
/* If this is not a case of ignoring a mismatch in signedness,
no warning. */
else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
@@ -10880,7 +10965,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
}
ret_stmt = build_stmt (loc, RETURN_EXPR, retval);
- TREE_NO_WARNING (ret_stmt) |= no_warning;
+ if (no_warning)
+ suppress_warning (ret_stmt, OPT_Wreturn_type);
return add_stmt (ret_stmt);
}
@@ -11156,7 +11242,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
;
else if (!TREE_SIDE_EFFECTS (expr))
{
- if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
+ if (!VOID_TYPE_P (TREE_TYPE (expr))
+ && !warning_suppressed_p (expr, OPT_Wunused_value))
warning_at (loc, OPT_Wunused_value, "statement with no effect");
}
else if (TREE_CODE (expr) == COMPOUND_EXPR)
@@ -11172,8 +11259,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
if (!TREE_SIDE_EFFECTS (r)
&& !VOID_TYPE_P (TREE_TYPE (r))
&& !CONVERT_EXPR_P (r)
- && !TREE_NO_WARNING (r)
- && !TREE_NO_WARNING (expr))
+ && !warning_suppressed_p (r, OPT_Wunused_value)
+ && !warning_suppressed_p (expr, OPT_Wunused_value))
warning_at (cloc, OPT_Wunused_value,
"right-hand operand of comma expression has no effect");
}
@@ -11342,7 +11429,7 @@ c_finish_stmt_expr (location_t loc, tree body)
last = c_wrap_maybe_const (last, true);
/* Do not warn if the return value of a statement expression is
unused. */
- TREE_NO_WARNING (last) = 1;
+ suppress_warning (last, OPT_Wunused);
return last;
}
@@ -12339,6 +12426,13 @@ build_binary_op (location_t location, enum tree_code code,
maybe_warn_bool_compare (location, code, orig_op0, orig_op1);
break;
+ case MIN_EXPR:
+ case MAX_EXPR:
+ /* Used for OpenMP atomics. */
+ gcc_assert (flag_openmp);
+ common = 1;
+ break;
+
default:
gcc_unreachable ();
}
@@ -13003,7 +13097,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
if (error_operand_p (t))
return error_mark_node;
ret = t;
- if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& TYPE_ATOMIC (strip_array_types (TREE_TYPE (t))))
{
error_at (OMP_CLAUSE_LOCATION (c), "%<_Atomic%> %qE in %qs clause",
@@ -13054,14 +13149,16 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
- else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& TYPE_ATOMIC (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c), "%<_Atomic%> %qD in %qs clause",
t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
- else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& VAR_P (t)
&& DECL_THREAD_LOCAL_P (t))
{
@@ -13070,7 +13167,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
&& TYPE_ATOMIC (TREE_TYPE (t))
&& POINTER_TYPE_P (TREE_TYPE (t)))
{
@@ -13141,7 +13239,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
{
if (!integer_nonzerop (length))
{
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
@@ -13209,7 +13308,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
}
if (tree_int_cst_equal (size, low_bound))
{
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
@@ -13230,7 +13330,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
}
else if (length == NULL_TREE)
{
- if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
@@ -13268,7 +13369,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
}
else if (length == NULL_TREE)
{
- if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
@@ -13313,6 +13415,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
/* If there is a pointer type anywhere but in the very first
array-section-subscript, the array section can't be contiguous. */
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
&& TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -13349,7 +13452,8 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
unsigned int first_non_one = 0;
auto_vec<tree, 10> types;
tree *tp = &OMP_CLAUSE_DECL (c);
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
&& TREE_CODE (*tp) == TREE_LIST
&& TREE_PURPOSE (*tp)
&& TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
@@ -13361,7 +13465,8 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
return true;
if (first == NULL_TREE)
return false;
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
{
tree t = *tp;
tree tem = NULL_TREE;
@@ -13556,35 +13661,33 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
&& TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
return false;
gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
- if (ort == C_ORT_OMP || ort == C_ORT_ACC)
- switch (OMP_CLAUSE_MAP_KIND (c))
- {
- case GOMP_MAP_ALLOC:
- case GOMP_MAP_IF_PRESENT:
- case GOMP_MAP_TO:
- case GOMP_MAP_FROM:
- case GOMP_MAP_TOFROM:
- case GOMP_MAP_ALWAYS_TO:
- case GOMP_MAP_ALWAYS_FROM:
- case GOMP_MAP_ALWAYS_TOFROM:
- case GOMP_MAP_RELEASE:
- case GOMP_MAP_DELETE:
- case GOMP_MAP_FORCE_TO:
- case GOMP_MAP_FORCE_FROM:
- case GOMP_MAP_FORCE_TOFROM:
- case GOMP_MAP_FORCE_PRESENT:
- OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
- break;
- default:
- break;
- }
+ switch (OMP_CLAUSE_MAP_KIND (c))
+ {
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_IF_PRESENT:
+ case GOMP_MAP_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DELETE:
+ case GOMP_MAP_FORCE_TO:
+ case GOMP_MAP_FORCE_FROM:
+ case GOMP_MAP_FORCE_TOFROM:
+ case GOMP_MAP_FORCE_PRESENT:
+ OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+ break;
+ default:
+ break;
+ }
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
- if (ort != C_ORT_OMP && ort != C_ORT_ACC)
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
- else if (TREE_CODE (t) == COMPONENT_REF)
+ if (TREE_CODE (t) == COMPONENT_REF)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
else
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
+ OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c);
if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
&& !c_mark_addressable (t))
return false;
@@ -13855,7 +13958,8 @@ tree
c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
- bitmap_head aligned_head, map_head, map_field_head, oacc_reduction_head;
+ bitmap_head aligned_head, map_head, map_field_head, map_firstprivate_head;
+ bitmap_head oacc_reduction_head;
tree c, t, type, *pc;
tree simdlen = NULL_TREE, safelen = NULL_TREE;
bool branch_seen = false;
@@ -13875,6 +13979,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
has been seen, -2 if mixed inscan/normal reduction diagnosed. */
int reduction_seen = 0;
bool allocate_seen = false;
+ bool implicit_moved = false;
+ bool target_in_reduction_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13884,8 +13990,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead. */
bitmap_initialize (&map_head, &bitmap_default_obstack);
bitmap_initialize (&map_field_head, &bitmap_default_obstack);
+ bitmap_initialize (&map_firstprivate_head, &bitmap_default_obstack);
/* If ort == C_ORT_OMP used as nontemporal_head or use_device_xxx_head
- instead. */
+ instead and for ort == C_ORT_OMP_TARGET used as in_reduction_head. */
bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack);
if (ort & C_ORT_ACC)
@@ -14037,6 +14144,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case PLUS_EXPR:
case MULT_EXPR:
case MINUS_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
break;
case MIN_EXPR:
if (TREE_CODE (type) == COMPLEX_TYPE)
@@ -14055,14 +14164,6 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case BIT_IOR_EXPR:
r_name = "|";
break;
- case TRUTH_ANDIF_EXPR:
- if (FLOAT_TYPE_P (type))
- r_name = "&&";
- break;
- case TRUTH_ORIF_EXPR:
- if (FLOAT_TYPE_P (type))
- r_name = "||";
- break;
default:
gcc_unreachable ();
}
@@ -14284,8 +14385,22 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|| (ort == C_ORT_OMP
&& (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
|| (OMP_CLAUSE_CODE (c)
- == OMP_CLAUSE_USE_DEVICE_ADDR))))
+ == OMP_CLAUSE_USE_DEVICE_ADDR)))
+ || (ort == C_ORT_OMP_TARGET
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION))
{
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ && (bitmap_bit_p (&generic_head, DECL_UID (t))
+ || bitmap_bit_p (&firstprivate_head, DECL_UID (t))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data-sharing "
+ "clauses", t);
+ remove = true;
+ break;
+ }
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
+ target_in_reduction_seen = true;
if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -14300,7 +14415,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t))
- || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+ || bitmap_bit_p (&lastprivate_head, DECL_UID (t))
+ || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE appears more than once in data clauses", t);
@@ -14322,6 +14438,37 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
case OMP_CLAUSE_FIRSTPRIVATE:
+ if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) && !implicit_moved)
+ {
+ move_implicit:
+ implicit_moved = true;
+ /* Move firstprivate and map clauses with
+ OMP_CLAUSE_{FIRSTPRIVATE,MAP}_IMPLICIT set to the end of
+ clauses chain. */
+ tree cl1 = NULL_TREE, cl2 = NULL_TREE;
+ tree *pc1 = pc, *pc2 = &cl1, *pc3 = &cl2;
+ while (*pc1)
+ if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (*pc1))
+ {
+ *pc3 = *pc1;
+ pc3 = &OMP_CLAUSE_CHAIN (*pc3);
+ *pc1 = OMP_CLAUSE_CHAIN (*pc1);
+ }
+ else if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_IMPLICIT (*pc1))
+ {
+ *pc2 = *pc1;
+ pc2 = &OMP_CLAUSE_CHAIN (*pc2);
+ *pc1 = OMP_CLAUSE_CHAIN (*pc1);
+ }
+ else
+ pc1 = &OMP_CLAUSE_CHAIN (*pc1);
+ *pc3 = NULL;
+ *pc2 = cl2;
+ *pc1 = cl1;
+ continue;
+ }
t = OMP_CLAUSE_DECL (c);
need_complete = true;
need_implicitly_determined = true;
@@ -14331,8 +14478,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"%qE is not a variable in clause %<firstprivate%>", t);
remove = true;
}
+ else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
+ && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c)
+ && bitmap_bit_p (&map_firstprivate_head, DECL_UID (t)))
+ remove = true;
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
- || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
+ || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE appears more than once in data clauses", t);
@@ -14343,6 +14495,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in data clauses", t);
+ else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
+ && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c))
+ /* Silently drop the clause. */;
else
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears both in data and map clauses", t);
@@ -14485,6 +14640,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
break;
}
+ /* FALLTHRU */
+ case OMP_CLAUSE_AFFINITY:
+ t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST
&& TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
@@ -14503,7 +14661,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
if (handle_omp_array_sections (c, ort))
remove = true;
- else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%<depend%> clause with %<depobj%> dependence "
@@ -14518,17 +14677,22 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE is not lvalue expression nor array section in "
- "%<depend%> clause", t);
+ "%qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (TREE_CODE (t) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (t, 1)))
{
+ gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY);
error_at (OMP_CLAUSE_LOCATION (c),
- "bit-field %qE in %qs clause", t, "depend");
+ "bit-field %qE in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
- else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
{
if (!c_omp_depend_t_p (TREE_TYPE (t)))
{
@@ -14539,7 +14703,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
}
}
- else if (c_omp_depend_t_p (TREE_TYPE (t)))
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && c_omp_depend_t_p (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE should not have %<omp_depend_t%> type in "
@@ -14571,6 +14736,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
case OMP_CLAUSE_MAP:
+ if (OMP_CLAUSE_MAP_IMPLICIT (c) && !implicit_moved)
+ goto move_implicit;
+ /* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
case OMP_CLAUSE__CACHE_:
@@ -14604,6 +14772,16 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
while (TREE_CODE (t) == COMPONENT_REF)
t = TREE_OPERAND (t, 0);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_IMPLICIT (c)
+ && (bitmap_bit_p (&map_head, DECL_UID (t))
+ || bitmap_bit_p (&map_field_head, DECL_UID (t))
+ || bitmap_bit_p (&map_firstprivate_head,
+ DECL_UID (t))))
+ {
+ remove = true;
+ break;
+ }
if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
break;
if (bitmap_bit_p (&map_head, DECL_UID (t)))
@@ -14710,7 +14888,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
{
if (bitmap_bit_p (&map_field_head, DECL_UID (t))
- || (ort == C_ORT_OMP
+ || (ort != C_ORT_ACC
&& bitmap_bit_p (&map_head, DECL_UID (t))))
break;
}
@@ -14758,10 +14936,17 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
}
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_IMPLICIT (c)
+ && (bitmap_bit_p (&map_head, DECL_UID (t))
+ || bitmap_bit_p (&map_field_head, DECL_UID (t))
+ || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))))
+ remove = true;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
{
if (bitmap_bit_p (&generic_head, DECL_UID (t))
- || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
+ || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in data clauses", t);
@@ -14778,10 +14963,10 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
}
else
- bitmap_set_bit (&generic_head, DECL_UID (t));
+ bitmap_set_bit (&map_firstprivate_head, DECL_UID (t));
}
else if (bitmap_bit_p (&map_head, DECL_UID (t))
- && (ort != C_ORT_OMP
+ && (ort == C_ORT_ACC
|| !bitmap_bit_p (&map_field_head, DECL_UID (t))))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
@@ -14795,8 +14980,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"%qD appears more than once in map clauses", t);
remove = true;
}
- else if (bitmap_bit_p (&generic_head, DECL_UID (t))
- && ort == C_ORT_ACC)
+ else if (ort == C_ORT_ACC
+ && bitmap_bit_p (&generic_head, DECL_UID (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in data clauses", t);
@@ -14890,7 +15075,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
{
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
- && ort == C_ORT_OMP)
+ && ort != C_ORT_ACC)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qs variable is not a pointer",
@@ -14982,6 +15167,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_THREADS:
case OMP_CLAUSE_SIMD:
case OMP_CLAUSE_HINT:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_DEFAULTMAP:
case OMP_CLAUSE_BIND:
case OMP_CLAUSE_NUM_GANGS:
@@ -14998,6 +15184,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_TILE:
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
+ case OMP_CLAUSE_NOHOST:
pc = &OMP_CLAUSE_CHAIN (c);
continue;
@@ -15175,7 +15362,10 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
reduction_seen = -2;
}
- if (linear_variable_step_check || reduction_seen == -2 || allocate_seen)
+ if (linear_variable_step_check
+ || reduction_seen == -2
+ || allocate_seen
+ || target_in_reduction_seen)
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
@@ -15223,6 +15413,20 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
&& reduction_seen == -2)
OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ if (target_in_reduction_seen
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
+ {
+ tree t = OMP_CLAUSE_DECL (c);
+ while (handled_component_p (t)
+ || TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ADDR_EXPR
+ || TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == NON_LVALUE_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (DECL_P (t)
+ && bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
+ OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1;
+ }
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
@@ -15313,7 +15517,7 @@ c_omp_clause_copy_ctor (tree clause, tree dst, tree src)
tree tmp = create_tmp_var (nonatomic_type);
tree tmp_addr = build_fold_addr_expr (tmp);
TREE_ADDRESSABLE (tmp) = 1;
- TREE_NO_WARNING (tmp) = 1;
+ suppress_warning (tmp);
tree src_addr = build_fold_addr_expr (src);
tree dst_addr = build_fold_addr_expr (dst);
tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 58b161b..c8d9db6 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -131,7 +131,7 @@ static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *);
static bool
c_parser_gimple_parse_bb_spec (tree val, int *index)
{
- if (strncmp (IDENTIFIER_POINTER (val), "__BB", 4) != 0)
+ if (!startswith (IDENTIFIER_POINTER (val), "__BB"))
return false;
for (const char *p = IDENTIFIER_POINTER (val) + 4; *p; ++p)
if (!ISDIGIT (*p))
@@ -877,6 +877,11 @@ c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq)
rhs.value = build3_loc (loc, COND_EXPR, TREE_TYPE (trueval.value),
rhs.value, trueval.value, falseval.value);
}
+ if (get_gimple_rhs_class (TREE_CODE (rhs.value)) == GIMPLE_INVALID_RHS)
+ {
+ c_parser_error (parser, "unexpected RHS for assignment");
+ return;
+ }
assign = gimple_build_assign (lhs.value, rhs.value);
gimple_seq_add_stmt_without_update (seq, assign);
gimple_set_location (assign, loc);
@@ -1754,6 +1759,12 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser,
c_parser_gimple_expr_list (parser, &exprlist);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
+ if (!FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr.value)))
+ {
+ c_parser_error (parser, "invalid call to non-function");
+ expr.set_error ();
+ break;
+ }
expr.value = build_call_array_loc
(expr_loc, TREE_TYPE (TREE_TYPE (expr.value)),
expr.value, exprlist.length (), exprlist.address ());
@@ -1887,7 +1898,8 @@ c_parser_gimple_label (gimple_parser &parser, gimple_seq *seq)
gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
c_parser_consume_token (parser);
tree label = define_label (loc1, name);
- gimple_seq_add_stmt_without_update (seq, gimple_build_label (label));
+ if (label)
+ gimple_seq_add_stmt_without_update (seq, gimple_build_label (label));
return;
}
@@ -2100,6 +2112,14 @@ c_parser_gimple_paren_condition (gimple_parser &parser)
if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return error_mark_node;
tree cond = c_parser_gimple_binary_expression (parser).value;
+ if (cond != error_mark_node
+ && ! COMPARISON_CLASS_P (cond)
+ && ! CONSTANT_CLASS_P (cond)
+ && ! SSA_VAR_P (cond))
+ {
+ c_parser_error (parser, "comparison required");
+ cond = error_mark_node;
+ }
if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
return error_mark_node;
return cond;