diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-01-03 21:40:04 +0100 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-01-03 21:40:04 +0100 |
commit | afae4a55ccaa0de95ea11e5f634084db6ab2f444 (patch) | |
tree | d632cc867d10410ba9fb750523be790b86846ac4 /gcc/c | |
parent | 9d9a82ec8478ff52c7a9d61f58cd2a7b6295b5f9 (diff) | |
parent | d2eb616a0f7bea78164912aa438c29fe1ef5774a (diff) | |
download | gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.zip gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.gz gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.bz2 |
Merge branch 'master' into devel/coarray_native
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 200 | ||||
-rw-r--r-- | gcc/c/Make-lang.in | 3 | ||||
-rw-r--r-- | gcc/c/c-aux-info.c | 1 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 52 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 646 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 235 | ||||
-rw-r--r-- | gcc/c/gimple-parser.c | 2 |
7 files changed, 817 insertions, 322 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 8c6893b..b5cf1a7 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,203 @@ +2020-12-16 Martin Uecker <muecker@gwdg.de> + + PR c/98047 + * c-typeck.c (build_modify_expr): Drop qualifiers. + +2020-12-16 Martin Uecker <muecker@gwdg.de> + + PR c/98260 + * c-parser.c (c_parser_expression): Look into + nop expression when marking expressions as read. + +2020-12-14 Martin Liska <mliska@suse.cz> + + PR sanitizer/98204 + * c-typeck.c (pointer_diff): Do not emit a top-level + sanitization. + (build_binary_op): Likewise. + +2020-12-09 Tobias Burnus <tobias@codesourcery.com> + + * c-parser.c (c_parser_omp_allocate): New. + (c_parser_omp_construct): Call it. + +2020-12-09 Richard Biener <rguenther@suse.de> + + PR c/98200 + * gimple-parser.c (c_parser_gimple_postfix_expression): Return + early on error. + +2020-12-07 Martin Uecker <muecker@gwdg.de> + + PR c/97981 + * c-typeck.c (convert_lvalue_to_rvalue): Move the code + that drops qualifiers to the end of the function. + +2020-11-26 Martin Uecker <muecker@gwdg.de> + + PR c/65455 + PR c/92935 + * c-parser.c (c_parser_declaration_or_fndef): Remove + redundant code to drop qualifiers of _Atomic types for __auto_type. + (c_parser_typeof_specifier): Do not drop qualifiers of _Atomic + types for __typeof__. + +2020-11-24 Jakub Jelinek <jakub@redhat.com> + + PR c/97958 + * c-parser.c (c_parser_binary_expression): For omp atomic binary + expressions, use make_node instead of build2 to avoid checking build2 + performs. + +2020-11-23 Joseph Myers <joseph@codesourcery.com> + + PR c/95630 + * c-typeck.c (build_binary_op): Use pedwarn_c99 with OPT_Wpedantic + for comparisons of complete and incomplete pointers. + +2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com> + + * c-aux-info.c (gen_type): Support opaque types. + +2020-11-20 Martin Sebor <msebor@redhat.com> + + PR middle-end/97879 + * c-decl.c (start_function): Set ATTR_FLAG_INTERNAL in flags. + +2020-11-20 Jakub Jelinek <jakub@redhat.com> + + PR other/97911 + * Make-lang.in (c.serial): Change from goal to a variable. + (.PHONY): Drop c.serial. + +2020-11-20 Martin Uecker <muecker@gwdg.de> + + * c-typeck.c (convert_lvalue_to_rvalue): Drop qualifiers. + +2020-11-19 Jakub Jelinek <jakub@redhat.com> + + PR c/97860 + * c-decl.c (get_parm_array_spec): Bail out of nelts is + error_operand_p. + +2020-11-18 Jakub Jelinek <jakub@redhat.com> + + * Make-lang.in (c.serial): New goal. + (.PHONY): Add c.serial c.prev. + (cc1$(exeext)): Call LINK_PROGRESS. + +2020-11-13 Vladimir N. Makarov <vmakarov@redhat.com> + + * c-parser.c (c_parser_asm_statement): Parse outputs for asm + goto too. + * c-typeck.c (build_asm_expr): Remove an assert checking output + absence for asm goto. + +2020-11-13 Jakub Jelinek <jakub@redhat.com> + + * c-typeck.c (c_finish_omp_clauses): Don't clear + OMP_CLAUSE_REDUCTION_INSCAN unless reduction_seen == -2. + +2020-11-13 Iain Sandoe <iain@sandoe.co.uk> + + PR objc/77404 + * c-parser.c (c_parser_objc_class_definition): Pass the + location of the class name to the interface declaration. + +2020-11-10 Strager Neds <strager.nds@gmail.com> + + * c-decl.c (merge_decls): Use new overload of + set_decl_section_name. + +2020-11-10 Chung-Lin Tang <cltang@codesourcery.com> + + * c-parser.c (c_parser_omp_target_data): Add use of + new c_omp_adjust_map_clauses function. Add GOMP_MAP_ATTACH_DETACH as + handled map clause kind. + (c_parser_omp_target_enter_data): Likewise. + (c_parser_omp_target_exit_data): Likewise. + (c_parser_omp_target): Likewise. + * c-typeck.c (handle_omp_array_sections): Adjust COMPONENT_REF case to + use GOMP_MAP_ATTACH_DETACH map kind for C_ORT_OMP region type. + (c_finish_omp_clauses): Adjust bitmap checks to allow struct decl and + same struct field access to co-exist on OpenMP construct. + +2020-11-07 Martin Uecker <muecker@gwdg.de> + + * c-parser.c (c_parser_label): Implement mixing of labels and code. + (c_parser_all_labels): Likewise. + +2020-11-06 Iain Sandoe <iain@sandoe.co.uk> + + * c-parser.c (c_parser_objc_at_property_declaration): + Improve parsing fidelity. Associate better location info + with @property attributes. Clean up the interface to + objc_add_property_declaration (). + +2020-11-06 Nathan Sidwell <nathan@acm.org> + + * c-decl.c (diagnose_mismatched_decls): Rename + DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN. + (warn_if_shadowing, implicitly_declare, names_builtin_p) + (collect_source_refs): Likewise. + * c-typeck.c (inform_declaration, inform_for_arg) + (convert_for_assignment): Likewise. + +2020-11-06 Tobias Burnus <tobias@codesourcery.com> + + * c-parser.c (c_parser_omp_atomic): Add openacc parameter and update + OpenACC matching. + (c_parser_omp_construct): Update call. + +2020-11-04 Jakub Jelinek <jakub@redhat.com> + + PR c++/97670 + * c-typeck.c (c_finish_omp_clauses): Look through array reductions to + find underlying decl to clear in the aligned_head bitmap. + +2020-11-04 Joseph Myers <joseph@codesourcery.com> + + * c-decl.c (handle_nodiscard_attribute): New. + (std_attribute_table): Add nodiscard. + * c-parser.c (c_parser_std_attribute): Expect argument to + nodiscard attribute to be a string. Do not special-case ignoring + nodiscard. + * c-typeck.c (maybe_warn_nodiscard): New. + (build_compound_expr, emit_side_effect_warnings): Call + maybe_warn_nodiscard. + (c_process_expr_stmt, c_finish_stmt_expr): Also call + emit_side_effect_warnings if warn_unused_result. + +2020-10-29 Asher Gordon <AsDaGo@posteo.net> + + * c-typeck.c (free_all_tagged_tu_seen_up_to): Replace free + with XDELETE. + (finish_init): Likewise. + (pop_init_level): Likewise. + +2020-10-28 Joseph Myers <joseph@codesourcery.com> + + * c-decl.c (store_parm_decls_newstyle): Use pedwarn_c11 not + error_at for omitted parameter name. + +2020-10-28 Jakub Jelinek <jakub@redhat.com> + + * c-parser.c (c_parser_omp_clause_name): Handle allocate. + (c_parser_omp_clause_allocate): New function. + (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ALLOCATE. + (OMP_FOR_CLAUSE_MASK, OMP_SECTIONS_CLAUSE_MASK, + OMP_PARALLEL_CLAUSE_MASK, OMP_SINGLE_CLAUSE_MASK, + OMP_TASK_CLAUSE_MASK, OMP_TASKGROUP_CLAUSE_MASK, + OMP_DISTRIBUTE_CLAUSE_MASK, OMP_TEAMS_CLAUSE_MASK, + OMP_TARGET_CLAUSE_MASK, OMP_TASKLOOP_CLAUSE_MASK): Add + PRAGMA_OMP_CLAUSE_ALLOCATE. + * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_ALLOCATE. + +2020-10-27 Joseph Myers <joseph@codesourcery.com> + + * c-parser.c (c_parser_std_attribute_specifier): Allow duplicate + standard attributes. + 2020-10-23 Marek Polacek <polacek@redhat.com> PR c++/91741 diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in index 7efc7c2..4b2e616 100644 --- a/gcc/c/Make-lang.in +++ b/gcc/c/Make-lang.in @@ -37,6 +37,7 @@ # # Define the names for selecting c in LANGUAGES. c: cc1$(exeext) +c.serial = cc1$(exeext) # Tell GNU make to ignore these if they exist. .PHONY: c gcc @@ -82,8 +83,10 @@ cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \ fi cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS) + @$(call LINK_PROGRESS,$(INDEX.c),start) +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \ cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS) + @$(call LINK_PROGRESS,$(INDEX.c),end) cc1.fda: ../stage1-gcc/cc1$(exeext) ../prev-gcc/$(PERF_DATA) $(CREATE_GCOV) -binary ../stage1-gcc/cc1$(exeext) -gcov cc1.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1 diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c index ffc8099..bdeef52 100644 --- a/gcc/c/c-aux-info.c +++ b/gcc/c/c-aux-info.c @@ -409,6 +409,7 @@ gen_type (const char *ret_val, tree t, formals_style style) data_type = concat ("unsigned ", data_type, NULL); break; + case OPAQUE_TYPE: case REAL_TYPE: data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); break; diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 1673b95..27f7722 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -2051,7 +2051,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, } } else if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_IS_BUILTIN (olddecl)) + && DECL_IS_UNDECLARED_BUILTIN (olddecl)) { /* A conflicting function declaration for a predeclared function that isn't actually built in. Objective C uses @@ -2265,7 +2265,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, built in, newdecl silently overrides olddecl. The latter occur only in Objective C; see also above. (FIXME: Make Objective C use normal builtins.) */ - if (!DECL_IS_BUILTIN (olddecl) + if (!DECL_IS_UNDECLARED_BUILTIN (olddecl) && !DECL_EXTERN_INLINE (olddecl)) { auto_diagnostic_group d; @@ -2884,7 +2884,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) || TREE_PUBLIC (olddecl) || TREE_STATIC (olddecl)) && DECL_SECTION_NAME (newdecl) != NULL) - set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl)); + set_decl_section_name (olddecl, newdecl); /* This isn't quite correct for something like int __thread x attribute ((tls_model ("local-exec"))); @@ -2978,7 +2978,7 @@ warn_if_shadowing (tree new_decl) || warn_shadow_local || warn_shadow_compatible_local) /* No shadow warnings for internally generated vars. */ - || DECL_IS_BUILTIN (new_decl)) + || DECL_IS_UNDECLARED_BUILTIN (new_decl)) return; /* Is anything being shadowed? Invisible decls do not count. */ @@ -3631,7 +3631,7 @@ implicitly_declare (location_t loc, tree functionid) in the external scope because they're pushed before the file scope gets created. Catch this here and rebind them into the file scope. */ - if (!fndecl_built_in_p (decl) && DECL_IS_BUILTIN (decl)) + if (!fndecl_built_in_p (decl) && DECL_IS_UNDECLARED_BUILTIN (decl)) { bind (functionid, decl, file_scope, /*invisible=*/false, /*nested=*/true, @@ -4400,6 +4400,31 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) } +/* Handle the standard [[nodiscard]] attribute. */ + +static tree +handle_nodiscard_attribute (tree *node, tree name, tree /*args*/, + int /*flags*/, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + { + if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))) + warning_at (DECL_SOURCE_LOCATION (*node), + OPT_Wattributes, "%qE attribute applied to %qD with void " + "return type", name, *node); + } + else if (RECORD_OR_UNION_TYPE_P (*node) + || TREE_CODE (*node) == ENUMERAL_TYPE) + /* OK */; + else + { + pedwarn (input_location, + OPT_Wattributes, "%qE attribute can only be applied to " + "functions or to structure, union or enumeration types", name); + *no_add_attrs = true; + } + return NULL_TREE; +} /* Table of supported standard (C2x) attributes. */ const struct attribute_spec std_attribute_table[] = { @@ -4411,6 +4436,8 @@ const struct attribute_spec std_attribute_table[] = handle_fallthrough_attribute, NULL }, { "maybe_unused", 0, 0, false, false, false, false, handle_unused_attribute, NULL }, + { "nodiscard", 0, 1, false, false, false, false, + handle_nodiscard_attribute, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; @@ -5748,6 +5775,8 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs) type = TREE_TYPE (type)) { tree nelts = array_type_nelts (type); + if (error_operand_p (nelts)) + return attrs; if (TREE_CODE (nelts) != INTEGER_CST) { /* Each variable VLA bound is represented by the dollar @@ -9569,7 +9598,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, current_function_decl = pushdecl (decl1); if (tree access = build_attr_access_from_parms (parms, false)) - decl_attributes (¤t_function_decl, access, 0, old_decl); + decl_attributes (¤t_function_decl, access, ATTR_FLAG_INTERNAL, + old_decl); push_scope (); declare_parm_level (); @@ -9630,7 +9660,9 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info) warn_if_shadowing (decl); } else - error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted"); + pedwarn_c11 (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, + "ISO C does not support omitting parameter names in " + "function definitions before C2X"); } /* Record the parameter list in the function declaration. */ @@ -10471,7 +10503,7 @@ names_builtin_p (const char *name) { tree id = get_identifier (name); if (tree decl = identifier_global_value (id)) - return TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl); + return TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_UNDECLARED_BUILTIN (decl); /* Also detect common reserved C words that aren't strictly built-in functions. */ @@ -12105,12 +12137,12 @@ collect_source_refs (void) { decls = DECL_INITIAL (t); for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl)) - if (!DECL_IS_BUILTIN (decl)) + if (!DECL_IS_UNDECLARED_BUILTIN (decl)) collect_source_ref (DECL_SOURCE_FILE (decl)); } for (decl = BLOCK_VARS (ext_block); decl; decl = TREE_CHAIN (decl)) - if (!DECL_IS_BUILTIN (decl)) + if (!DECL_IS_UNDECLARED_BUILTIN (decl)) collect_source_ref (DECL_SOURCE_FILE (decl)); } diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index b6a7ef4..b9fdc90 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1521,7 +1521,7 @@ static void c_parser_initval (c_parser *, struct c_expr *, struct obstack *); static tree c_parser_compound_statement (c_parser *, location_t * = NULL); static location_t c_parser_compound_statement_nostart (c_parser *); -static void c_parser_label (c_parser *); +static void c_parser_label (c_parser *, tree); static void c_parser_statement (c_parser *, bool *, location_t * = NULL); static void c_parser_statement_after_labels (c_parser *, bool *, vec<tree> * = NULL); @@ -2224,10 +2224,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, " initializer"); init = convert_lvalue_to_rvalue (init_loc, init, true, true); tree init_type = TREE_TYPE (init.value); - /* As with typeof, remove all qualifiers from atomic types. */ - if (init_type != error_mark_node && TYPE_ATOMIC (init_type)) - init_type - = c_build_qualified_type (init_type, TYPE_UNQUALIFIED); bool vm_type = variably_modified_type_p (init_type, NULL_TREE); if (vm_type) @@ -3743,11 +3739,6 @@ c_parser_typeof_specifier (c_parser *parser) if (was_vm) ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands); pop_maybe_used (was_vm); - /* For use in macros such as those in <stdatomic.h>, remove all - qualifiers from atomic types. (const can be an issue for more macros - using typeof than just the <stdatomic.h> ones.) */ - if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec)) - ret.spec = c_build_qualified_type (ret.spec, TYPE_UNQUALIFIED); } parens.skip_until_found_close (parser); return ret; @@ -4950,7 +4941,8 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) && attribute_takes_identifier_p (name)); bool require_string = (ns == NULL_TREE - && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0); + && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0 + || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0)); TREE_VALUE (attribute) = c_parser_attribute_arguments (parser, takes_identifier, require_string, false); @@ -4960,13 +4952,12 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) parens.require_close (parser); } out: - if (ns == NULL_TREE && !for_tm && !as && !is_attribute_p ("nodiscard", name)) + if (ns == NULL_TREE && !for_tm && !as) { /* An attribute with standard syntax and no namespace specified is a constraint violation if it is not one of the known - standard attributes (of which nodiscard is the only one - without a handler in GCC). Diagnose it here with a pedwarn - and then discard it to prevent a duplicate warning later. */ + standard attributes. Diagnose it here with a pedwarn and + then discard it to prevent a duplicate warning later. */ pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored", name); return error_mark_node; @@ -4977,9 +4968,6 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) static tree c_parser_std_attribute_specifier (c_parser *parser, bool for_tm) { - bool seen_deprecated = false; - bool seen_fallthrough = false; - bool seen_maybe_unused = false; location_t loc = c_parser_peek_token (parser)->location; if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>")) return NULL_TREE; @@ -5005,55 +4993,8 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm) tree attribute = c_parser_std_attribute (parser, for_tm); if (attribute != error_mark_node) { - bool duplicate = false; - tree name = get_attribute_name (attribute); - tree ns = get_attribute_namespace (attribute); - if (ns == NULL_TREE) - { - /* Some standard attributes may appear at most once in - each attribute list. Diagnose duplicates and remove - them from the list to avoid subsequent diagnostics - such as the more general one for multiple - "fallthrough" attributes in the same place (including - in separate attribute lists in the same attribute - specifier sequence, which is not a constraint - violation). */ - if (is_attribute_p ("deprecated", name)) - { - if (seen_deprecated) - { - error ("attribute %<deprecated%> can appear at most " - "once in an attribute-list"); - duplicate = true; - } - seen_deprecated = true; - } - else if (is_attribute_p ("fallthrough", name)) - { - if (seen_fallthrough) - { - error ("attribute %<fallthrough%> can appear at most " - "once in an attribute-list"); - duplicate = true; - } - seen_fallthrough = true; - } - else if (is_attribute_p ("maybe_unused", name)) - { - if (seen_maybe_unused) - { - error ("attribute %<maybe_unused%> can appear at most " - "once in an attribute-list"); - duplicate = true; - } - seen_maybe_unused = true; - } - } - if (!duplicate) - { - TREE_CHAIN (attribute) = attributes; - attributes = attribute; - } + TREE_CHAIN (attribute) = attributes; + attributes = attribute; } if (c_parser_next_token_is_not (parser, CPP_COMMA)) break; @@ -5573,7 +5514,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, } /* Parse a compound statement (possibly a function body) (C90 6.6.2, - C99 6.8.2, C11 6.8.2). + C99 6.8.2, C11 6.8.2, C2X 6.8.2). compound-statement: { block-item-list[opt] } @@ -5584,6 +5525,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, block-item-list block-item block-item: + label nested-declaration statement @@ -5724,7 +5666,7 @@ c_parser_compound_statement_nostart (c_parser *parser) { location_t loc = c_parser_peek_token (parser)->location; loc = expansion_point_location_if_in_system_header (loc); - /* Standard attributes may start a statement or a declaration. */ + /* Standard attributes may start a label, statement or declaration. */ bool have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1); tree std_attrs = NULL_TREE; @@ -5735,7 +5677,6 @@ c_parser_compound_statement_nostart (c_parser *parser) || (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) { - c_warn_unused_attributes (std_attrs); if (c_parser_next_token_is_keyword (parser, RID_CASE)) label_loc = c_parser_peek_2nd_token (parser)->location; else @@ -5743,27 +5684,31 @@ c_parser_compound_statement_nostart (c_parser *parser) last_label = true; last_stmt = false; mark_valid_location_for_stdc_pragma (false); - c_parser_label (parser); + c_parser_label (parser, std_attrs); } - else if (!last_label - && (c_parser_next_tokens_start_declaration (parser) - || (have_std_attrs - && c_parser_next_token_is (parser, CPP_SEMICOLON)))) + else if (c_parser_next_tokens_start_declaration (parser) + || (have_std_attrs + && c_parser_next_token_is (parser, CPP_SEMICOLON))) { - last_label = false; + if (last_label) + pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic, + "a label can only be part of a statement and " + "a declaration is not a statement"); + mark_valid_location_for_stdc_pragma (false); 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, &fallthru_attr_p); + if (last_stmt && !fallthru_attr_p) pedwarn_c90 (loc, OPT_Wdeclaration_after_statement, "ISO C90 forbids mixed declarations and code"); last_stmt = fallthru_attr_p; + last_label = false; } - else if (!last_label - && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) + else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) { /* __extension__ can start a declaration, but is also an unary operator that can start an expression. Consume all @@ -5846,7 +5791,7 @@ c_parser_compound_statement_nostart (c_parser *parser) parser->error = false; } if (last_label) - error_at (label_loc, "label at end of compound statement"); + pedwarn_c11 (label_loc, OPT_Wpedantic, "label at end of compound statement"); location_t endloc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); /* Restore the value we started with. */ @@ -5862,19 +5807,29 @@ c_parser_compound_statement_nostart (c_parser *parser) static void c_parser_all_labels (c_parser *parser) { + tree std_attrs = NULL; if (c_parser_nth_token_starts_std_attributes (parser, 1)) { - tree std_attrs = c_parser_std_attribute_specifier_sequence (parser); + std_attrs = c_parser_std_attribute_specifier_sequence (parser); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) c_parser_error (parser, "expected statement"); - else - c_warn_unused_attributes (std_attrs); } while (c_parser_next_token_is_keyword (parser, RID_CASE) || c_parser_next_token_is_keyword (parser, RID_DEFAULT) || (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) - c_parser_label (parser); + { + c_parser_label (parser, std_attrs); + std_attrs = NULL; + if (c_parser_nth_token_starts_std_attributes (parser, 1)) + { + std_attrs = c_parser_std_attribute_specifier_sequence (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + c_parser_error (parser, "expected statement"); + } + } + if (std_attrs) + c_warn_unused_attributes (std_attrs); } /* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1). @@ -5896,9 +5851,8 @@ c_parser_all_labels (c_parser *parser) in the caller, to distinguish statements from declarations. Any attribute-specifier-sequence after the label is parsed in this function. */ - static void -c_parser_label (c_parser *parser) +c_parser_label (c_parser *parser, tree std_attrs) { location_t loc1 = c_parser_peek_token (parser)->location; tree label = NULL_TREE; @@ -5948,8 +5902,13 @@ c_parser_label (c_parser *parser) if (tlab) { decl_attributes (&tlab, attrs, 0); + decl_attributes (&tlab, std_attrs, 0); label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab)); } + if (attrs + && c_parser_next_tokens_start_declaration (parser)) + warning_at (loc2, OPT_Wattributes, "GNU-style attribute between" + " label and declaration appertains to the label"); } if (label) { @@ -5957,55 +5916,6 @@ c_parser_label (c_parser *parser) FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p; else FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p; - - /* Standard attributes are only allowed here if they start a - statement, not a declaration (including the case of an - attribute-declaration with only attributes). */ - bool have_std_attrs - = c_parser_nth_token_starts_std_attributes (parser, 1); - tree std_attrs = NULL_TREE; - if (have_std_attrs) - std_attrs = c_parser_std_attribute_specifier_sequence (parser); - - /* Allow '__attribute__((fallthrough));'. */ - if (!have_std_attrs - && c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) - { - location_t loc = c_parser_peek_token (parser)->location; - tree attrs = c_parser_gnu_attributes (parser); - if (attribute_fallthrough_p (attrs)) - { - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - tree fn = build_call_expr_internal_loc (loc, - IFN_FALLTHROUGH, - void_type_node, 0); - add_stmt (fn); - } - else - warning_at (loc, OPT_Wattributes, "%<fallthrough%> attribute " - "not followed by %<;%>"); - } - else if (attrs != NULL_TREE) - warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>" - " can be applied to a null statement"); - } - if (c_parser_next_tokens_start_declaration (parser) - || (have_std_attrs - && c_parser_next_token_is (parser, CPP_SEMICOLON))) - { - error_at (c_parser_peek_token (parser)->location, - "a label can only be part of a statement and " - "a declaration is not a statement"); - c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, - /*static_assert_ok*/ true, - /*empty_ok*/ true, /*nested*/ true, - /*start_attr_ok*/ true, NULL, - vNULL, have_std_attrs, std_attrs); - } - else if (std_attrs) - /* Nonempty attributes on the following statement are ignored. */ - c_warn_unused_attributes (std_attrs); } } @@ -7225,10 +7135,7 @@ c_parser_asm_statement (c_parser *parser) switch (section) { case 0: - /* For asm goto, we don't allow output operands, but reserve - the slot for a future extension that does allow them. */ - if (!is_goto) - outputs = c_parser_asm_operands (parser); + outputs = c_parser_asm_operands (parser); break; case 1: inputs = c_parser_asm_operands (parser); @@ -7949,9 +7856,13 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after, && 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))) \ - stack[0].expr.value \ - = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \ - stack[0].expr.value, stack[1].expr.value); \ + { \ + tree t = make_node (stack[1].op); \ + TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \ + TREE_OPERAND (t, 0) = stack[0].expr.value; \ + TREE_OPERAND (t, 1) = stack[1].expr.value; \ + stack[0].expr.value = t; \ + } \ else \ stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ stack[sp].op, \ @@ -10704,8 +10615,14 @@ c_parser_expression (c_parser *parser) c_parser_consume_token (parser); expr_loc = c_parser_peek_token (parser)->location; lhsval = expr.value; - while (TREE_CODE (lhsval) == COMPOUND_EXPR) - lhsval = TREE_OPERAND (lhsval, 1); + while (TREE_CODE (lhsval) == COMPOUND_EXPR + || TREE_CODE (lhsval) == NOP_EXPR) + { + if (TREE_CODE (lhsval) == COMPOUND_EXPR) + lhsval = TREE_OPERAND (lhsval, 1); + else + lhsval = TREE_OPERAND (lhsval, 0); + } if (DECL_P (lhsval) || handled_component_p (lhsval)) mark_exp_read (lhsval); next = c_parser_expr_no_commas (parser, NULL); @@ -10882,6 +10799,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) return; } id1 = c_parser_peek_token (parser)->value; + location_t loc1 = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { @@ -10941,7 +10859,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) tree proto = NULL_TREE; if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); - objc_start_class_interface (id1, superclass, proto, attributes); + objc_start_class_interface (id1, loc1, superclass, proto, attributes); } else objc_start_class_implementation (id1, superclass); @@ -12008,158 +11926,196 @@ c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, static void c_parser_objc_at_property_declaration (c_parser *parser) { - /* The following variables hold the attributes of the properties as - parsed. They are 'false' or 'NULL_TREE' if the attribute was not - seen. When we see an attribute, we set them to 'true' (if they - are boolean properties) or to the identifier (if they have an - argument, ie, for getter and setter). Note that here we only - parse the list of attributes, check the syntax and accumulate the - attributes that we find. objc_add_property_declaration() will - then process the information. */ - bool property_assign = false; - bool property_copy = false; - tree property_getter_ident = NULL_TREE; - bool property_nonatomic = false; - bool property_readonly = false; - bool property_readwrite = false; - bool property_retain = false; - tree property_setter_ident = NULL_TREE; - - /* 'properties' is the list of properties that we read. Usually a - single one, but maybe more (eg, in "@property int a, b, c;" there - are three). */ - tree properties; - location_t loc; - - loc = c_parser_peek_token (parser)->location; gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY)); - + location_t loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); /* Eat '@property'. */ - /* Parse the optional attribute list... */ + /* Parse the optional attribute list. + + A list of parsed, but not verified, attributes. */ + vec<property_attribute_info *> prop_attr_list = vNULL; + + bool syntax_error = false; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { matching_parens parens; + location_t attr_start = c_parser_peek_token (parser)->location; /* Eat the '(' */ parens.consume_open (parser); /* Property attribute keywords are valid now. */ parser->objc_property_attr_context = true; - while (true) + /* Allow @property (), with a warning. */ + location_t attr_end = c_parser_peek_token (parser)->location; + + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) { - bool syntax_error = false; - c_token *token = c_parser_peek_token (parser); - enum rid keyword; + location_t attr_comb = make_location (attr_end, attr_start, attr_end); + warning_at (attr_comb, OPT_Wattributes, + "empty property attribute list"); + } + else + while (true) + { + c_token *token = c_parser_peek_token (parser); + attr_start = token->location; + attr_end = get_finish (token->location); + location_t attr_comb = make_location (attr_start, attr_start, + attr_end); - if (token->type != CPP_KEYWORD) - { - if (token->type == CPP_CLOSE_PAREN) - c_parser_error (parser, "expected identifier"); - else - { - c_parser_consume_token (parser); - c_parser_error (parser, "unknown property attribute"); - } - break; - } - keyword = token->keyword; - c_parser_consume_token (parser); - switch (keyword) - { - case RID_ASSIGN: property_assign = true; break; - case RID_COPY: property_copy = true; break; - case RID_NONATOMIC: property_nonatomic = true; break; - case RID_READONLY: property_readonly = true; break; - case RID_READWRITE: property_readwrite = true; break; - case RID_RETAIN: property_retain = true; break; - - case RID_GETTER: - case RID_SETTER: - if (c_parser_next_token_is_not (parser, CPP_EQ)) - { - if (keyword == RID_GETTER) - c_parser_error (parser, - "missing %<=%> (after %<getter%> attribute)"); - else - c_parser_error (parser, - "missing %<=%> (after %<setter%> attribute)"); - syntax_error = true; - break; - } - c_parser_consume_token (parser); /* eat the = */ - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - syntax_error = true; + if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA) + { + warning_at (attr_comb, OPT_Wattributes, + "missing property attribute"); + if (token->type == CPP_CLOSE_PAREN) break; - } - if (keyword == RID_SETTER) - { - if (property_setter_ident != NULL_TREE) - c_parser_error (parser, "the %<setter%> attribute may only be specified once"); - else - property_setter_ident = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, CPP_COLON)) - c_parser_error (parser, "setter name must terminate with %<:%>"); - else - c_parser_consume_token (parser); - } - else - { - if (property_getter_ident != NULL_TREE) - c_parser_error (parser, "the %<getter%> attribute may only be specified once"); - else - property_getter_ident = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - } - break; - default: - c_parser_error (parser, "unknown property attribute"); - syntax_error = true; - break; + c_parser_consume_token (parser); + continue; + } + + tree attr_name = NULL_TREE; + enum rid keyword = RID_MAX; /* Not a valid property attribute. */ + bool add_at = false; + if (token->type == CPP_KEYWORD) + { + keyword = token->keyword; + if (OBJC_IS_AT_KEYWORD (keyword)) + { + /* For '@' keywords the token value has the keyword, + prepend the '@' for diagnostics. */ + attr_name = token->value; + add_at = true; + } + else + attr_name = ridpointers[(int)keyword]; + } + else if (token->type == CPP_NAME) + attr_name = token->value; + c_parser_consume_token (parser); + + enum objc_property_attribute_kind prop_kind + = objc_prop_attr_kind_for_rid (keyword); + property_attribute_info *prop + = new property_attribute_info (attr_name, attr_comb, prop_kind); + prop_attr_list.safe_push (prop); + + tree meth_name; + switch (prop->prop_kind) + { + default: break; + case OBJC_PROPERTY_ATTR_UNKNOWN: + if (attr_name) + error_at (attr_comb, "unknown property attribute %<%s%s%>", + add_at ? "@" : "", IDENTIFIER_POINTER (attr_name)); + else + error_at (attr_comb, "unknown property attribute"); + prop->parse_error = syntax_error = true; + break; + + case OBJC_PROPERTY_ATTR_GETTER: + case OBJC_PROPERTY_ATTR_SETTER: + if (c_parser_next_token_is_not (parser, CPP_EQ)) + { + attr_comb = make_location (attr_end, attr_start, attr_end); + error_at (attr_comb, "expected %<=%> after Objective-C %qE", + attr_name); + prop->parse_error = syntax_error = true; + break; + } + token = c_parser_peek_token (parser); + attr_end = token->location; + c_parser_consume_token (parser); /* eat the = */ + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + attr_comb = make_location (attr_end, attr_start, attr_end); + error_at (attr_comb, "expected %qE selector name", + attr_name); + prop->parse_error = syntax_error = true; + break; + } + /* Get the end of the method name, and consume the name. */ + token = c_parser_peek_token (parser); + attr_end = get_finish (token->location); + meth_name = token->value; + c_parser_consume_token (parser); + if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER) + { + if (c_parser_next_token_is_not (parser, CPP_COLON)) + { + attr_comb = make_location (attr_end, attr_start, + attr_end); + error_at (attr_comb, "setter method names must" + " terminate with %<:%>"); + prop->parse_error = syntax_error = true; + } + else + { + attr_end = get_finish (c_parser_peek_token + (parser)->location); + c_parser_consume_token (parser); + } + attr_comb = make_location (attr_start, attr_start, + attr_end); + } + else + attr_comb = make_location (attr_start, attr_start, + attr_end); + prop->ident = meth_name; + /* Updated location including all that was successfully + parsed. */ + prop->prop_loc = attr_comb; + break; } - if (syntax_error) - break; - + /* If we see a comma here, then keep going - even if we already + saw a syntax error. For simple mistakes e.g. (asign, getter=x) + this makes a more useful output and avoid spurious warnings about + missing attributes that are, in fact, specified after the one with + the syntax error. */ if (c_parser_next_token_is (parser, CPP_COMMA)) c_parser_consume_token (parser); else break; } parser->objc_property_attr_context = false; - parens.skip_until_found_close (parser); - } - /* ... and the property declaration(s). */ - properties = c_parser_struct_declaration (parser); - if (properties == error_mark_node) - { - c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); - parser->error = false; - return; + if (syntax_error && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) + /* We don't really want to chew the whole of the file looking for a + matching closing parenthesis, so we will try to read the decl and + let the error handling for that close out the statement. */ + ; + else + syntax_error = false, parens.skip_until_found_close (parser); } - if (properties == NULL_TREE) - c_parser_error (parser, "expected identifier"); + /* 'properties' is the list of properties that we read. Usually a + single one, but maybe more (eg, in "@property int a, b, c;" there + are three). */ + tree properties = c_parser_struct_declaration (parser); + + if (properties == error_mark_node) + c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); else { - /* Comma-separated properties are chained together in - reverse order; add them one by one. */ - properties = nreverse (properties); - - for (; properties; properties = TREE_CHAIN (properties)) - objc_add_property_declaration (loc, copy_node (properties), - property_readonly, property_readwrite, - property_assign, property_retain, - property_copy, property_nonatomic, - property_getter_ident, property_setter_ident); + if (properties == NULL_TREE) + c_parser_error (parser, "expected identifier"); + else + { + /* Comma-separated properties are chained together in reverse order; + add them one by one. */ + properties = nreverse (properties); + for (; properties; properties = TREE_CHAIN (properties)) + objc_add_property_declaration (loc, copy_node (properties), + prop_attr_list); + } + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + while (!prop_attr_list.is_empty()) + delete prop_attr_list.pop (); + prop_attr_list.release (); parser->error = false; } @@ -12653,6 +12609,8 @@ c_parser_omp_clause_name (c_parser *parser) case 'a': if (!strcmp ("aligned", p)) result = PRAGMA_OMP_CLAUSE_ALIGNED; + else if (!strcmp ("allocate", p)) + result = PRAGMA_OMP_CLAUSE_ALLOCATE; else if (!strcmp ("async", p)) result = PRAGMA_OACC_CLAUSE_ASYNC; else if (!strcmp ("attach", p)) @@ -15162,6 +15120,62 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list) return nl; } +/* OpenMP 5.0: + allocate ( variable-list ) + allocate ( expression : variable-list ) */ + +static tree +c_parser_omp_clause_allocate (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + tree nl, c; + tree allocator = NULL_TREE; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if ((c_parser_next_token_is_not (parser, CPP_NAME) + && c_parser_next_token_is_not (parser, CPP_KEYWORD)) + || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA + && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN)) + { + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + allocator = expr.value; + allocator = c_fully_fold (allocator, false, NULL); + tree orig_type + = expr.original_type ? expr.original_type : TREE_TYPE (allocator); + orig_type = TYPE_MAIN_VARIANT (orig_type); + if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator)) + || TREE_CODE (orig_type) != ENUMERAL_TYPE + || TYPE_NAME (orig_type) != get_identifier ("omp_allocator_handle_t")) + { + error_at (clause_loc, "%<allocate%> clause allocator expression " + "has type %qT rather than " + "%<omp_allocator_handle_t%>", + TREE_TYPE (allocator)); + allocator = NULL_TREE; + } + if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) + { + parens.skip_until_found_close (parser); + return list; + } + } + + nl = c_parser_omp_variable_list (parser, clause_loc, + OMP_CLAUSE_ALLOCATE, list); + + if (allocator) + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; + + parens.skip_until_found_close (parser); + return nl; +} + /* OpenMP 4.0: linear ( variable-list ) linear ( variable-list : expression ) @@ -16404,6 +16418,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_aligned (parser, clauses); c_name = "aligned"; break; + case PRAGMA_OMP_CLAUSE_ALLOCATE: + clauses = c_parser_omp_clause_allocate (parser, clauses); + c_name = "allocate"; + break; case PRAGMA_OMP_CLAUSE_LINEAR: clauses = c_parser_omp_clause_linear (parser, clauses); c_name = "linear"; @@ -17238,6 +17256,55 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name) return stmt; } +/* OpenMP 5.0: + # pragma omp allocate (list) [allocator(allocator)] */ + +static void +c_parser_omp_allocate (location_t loc, c_parser *parser) +{ + tree allocator = NULL_TREE; + tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + matching_parens parens; + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + if (strcmp ("allocator", p) != 0) + error_at (c_parser_peek_token (parser)->location, + "expected %<allocator%>"); + else 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); + allocator = expr.value; + allocator = c_fully_fold (allocator, false, NULL); + tree orig_type + = expr.original_type ? expr.original_type : TREE_TYPE (allocator); + orig_type = TYPE_MAIN_VARIANT (orig_type); + if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator)) + || TREE_CODE (orig_type) != ENUMERAL_TYPE + || TYPE_NAME (orig_type) + != get_identifier ("omp_allocator_handle_t")) + { + error_at (expr_loc, "%<allocator%> clause allocator expression " + "has type %qT rather than " + "%<omp_allocator_handle_t%>", + TREE_TYPE (allocator)); + allocator = NULL_TREE; + } + parens.skip_until_found_close (parser); + } + } + c_parser_skip_to_pragma_eol (parser); + + if (allocator) + for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; + + sorry_at (loc, "%<#pragma omp allocate%> not yet supported"); +} + /* OpenMP 2.5: # pragma omp atomic new-line expression-stmt @@ -17292,7 +17359,7 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name) LOC is the location of the #pragma token. */ static void -c_parser_omp_atomic (location_t loc, c_parser *parser) +c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc) { tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE; tree lhs1 = NULL_TREE, rhs1 = NULL_TREE; @@ -17331,6 +17398,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) new_code = OMP_ATOMIC; else if (!strcmp (p, "capture")) new_code = OMP_ATOMIC_CAPTURE_NEW; + else if (openacc) + { + p = NULL; + error_at (cloc, "expected %<read%>, %<write%>, %<update%>, " + "or %<capture%> clause"); + } else if (!strcmp (p, "seq_cst")) new_memory_order = OMP_MEMORY_ORDER_SEQ_CST; else if (!strcmp (p, "acq_rel")) @@ -17358,7 +17431,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) { if (new_code != ERROR_MARK) { - if (code != ERROR_MARK) + /* OpenACC permits 'update capture'. */ + if (openacc + && code == OMP_ATOMIC + && new_code == OMP_ATOMIC_CAPTURE_NEW) + code = new_code; + else if (code != ERROR_MARK) error_at (cloc, "too many atomic clauses"); else code = new_code; @@ -17380,7 +17458,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) if (code == ERROR_MARK) code = OMP_ATOMIC; - if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED) + if (openacc) + memory_order = OMP_MEMORY_ORDER_RELAXED; + else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED) { omp_requires_mask = (enum omp_requires) (omp_requires_mask @@ -17436,6 +17516,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) } 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) { @@ -18584,6 +18665,7 @@ c_parser_omp_simd (location_t loc, c_parser *parser, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) static tree @@ -18875,6 +18957,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) static tree @@ -18929,6 +19012,7 @@ c_parser_omp_sections (location_t loc, c_parser *parser, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND)) static tree @@ -19070,6 +19154,7 @@ c_parser_omp_parallel (location_t loc, c_parser *parser, ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) static tree @@ -19104,6 +19189,7 @@ c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | (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)) static tree @@ -19174,7 +19260,8 @@ c_parser_omp_taskyield (c_parser *parser) */ #define OMP_TASKGROUP_CLAUSE_MASK \ - ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION)) + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION)) static tree c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p) @@ -19275,6 +19362,7 @@ c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) static tree @@ -19364,6 +19452,7 @@ c_parser_omp_distribute (location_t loc, c_parser *parser, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT)) static tree @@ -19470,6 +19559,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p) tree clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK, "#pragma omp target data"); + c_omp_adjust_map_clauses (clauses, false); int map_seen = 0; for (tree *pc = &clauses; *pc;) { @@ -19487,6 +19577,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p) break; case GOMP_MAP_FIRSTPRIVATE_POINTER: case GOMP_MAP_ALWAYS_POINTER: + case GOMP_MAP_ATTACH_DETACH: break; default: map_seen |= 1; @@ -19610,6 +19701,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser, tree clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK, "#pragma omp target enter data"); + c_omp_adjust_map_clauses (clauses, false); int map_seen = 0; for (tree *pc = &clauses; *pc;) { @@ -19623,6 +19715,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser, break; case GOMP_MAP_FIRSTPRIVATE_POINTER: case GOMP_MAP_ALWAYS_POINTER: + case GOMP_MAP_ATTACH_DETACH: break; default: map_seen |= 1; @@ -19694,7 +19787,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser, tree clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK, "#pragma omp target exit data"); - + c_omp_adjust_map_clauses (clauses, false); int map_seen = 0; for (tree *pc = &clauses; *pc;) { @@ -19709,6 +19802,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser, break; case GOMP_MAP_FIRSTPRIVATE_POINTER: case GOMP_MAP_ALWAYS_POINTER: + case GOMP_MAP_ATTACH_DETACH: break; default: map_seen |= 1; @@ -19751,6 +19845,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | (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_IS_DEVICE_PTR)) @@ -19918,6 +20013,8 @@ 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"); + c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true); + pc = &OMP_TARGET_CLAUSES (stmt); keep_next_level (); block = c_begin_compound_stmt (true); @@ -19942,6 +20039,7 @@ check_clauses: case GOMP_MAP_ALLOC: case GOMP_MAP_FIRSTPRIVATE_POINTER: case GOMP_MAP_ALWAYS_POINTER: + case GOMP_MAP_ATTACH_DETACH: break; default: error_at (OMP_CLAUSE_LOCATION (*pc), @@ -21381,6 +21479,7 @@ c_finish_taskloop_clauses (tree clauses) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION)) @@ -21467,7 +21566,7 @@ c_parser_omp_construct (c_parser *parser, bool *if_p) switch (p_kind) { case PRAGMA_OACC_ATOMIC: - c_parser_omp_atomic (loc, parser); + c_parser_omp_atomic (loc, parser, true); return; case PRAGMA_OACC_CACHE: strcpy (p_name, "#pragma acc"); @@ -21493,8 +21592,11 @@ c_parser_omp_construct (c_parser *parser, bool *if_p) strcpy (p_name, "#pragma wait"); stmt = c_parser_oacc_wait (loc, parser, p_name); break; + case PRAGMA_OMP_ALLOCATE: + c_parser_omp_allocate (loc, parser); + return; case PRAGMA_OMP_ATOMIC: - c_parser_omp_atomic (loc, parser); + c_parser_omp_atomic (loc, parser, false); return; case PRAGMA_OMP_CRITICAL: stmt = c_parser_omp_critical (loc, parser, if_p); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 459090e..f68cb01 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -1407,7 +1407,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til) const struct tagged_tu_seen_cache *const tu1 = (const struct tagged_tu_seen_cache *) tu; tu = tu1->next; - free (CONST_CAST (struct tagged_tu_seen_cache *, tu1)); + XDELETE (CONST_CAST (struct tagged_tu_seen_cache *, tu1)); } tagged_tu_seen_base = tu_til; } @@ -2116,6 +2116,9 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp, exp.value = build4 (TARGET_EXPR, nonatomic_type, tmp, func_call, NULL_TREE, NULL_TREE); } + if (convert_p && !error_operand_p (exp.value) + && (TREE_CODE (TREE_TYPE (exp.value)) != ARRAY_TYPE)) + exp.value = convert (build_qualified_type (TREE_TYPE (exp.value), TYPE_UNQUALIFIED), exp.value); return exp; } @@ -3014,7 +3017,8 @@ build_function_call (location_t loc, tree function, tree params) static void inform_declaration (tree decl) { - if (decl && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_IS_BUILTIN (decl))) + if (decl && (TREE_CODE (decl) != FUNCTION_DECL + || !DECL_IS_UNDECLARED_BUILTIN (decl))) inform (DECL_SOURCE_LOCATION (decl), "declared here"); } @@ -3945,10 +3949,9 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr) pedwarn (loc, OPT_Wpointer_arith, "pointer to a function used in subtraction"); - if (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT)) + if (current_function_decl != NULL_TREE + && sanitize_flags_p (SANITIZE_POINTER_SUBTRACT)) { - gcc_assert (current_function_decl != NULL_TREE); - op0 = save_expr (op0); op1 = save_expr (op1); @@ -5490,6 +5493,82 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, return ret; } +/* EXPR is an expression, location LOC, whose result is discarded. + Warn if it is a call to a nodiscard function (or a COMPOUND_EXPR + whose right-hand operand is such a call, possibly recursively). */ + +static void +maybe_warn_nodiscard (location_t loc, tree expr) +{ + if (VOID_TYPE_P (TREE_TYPE (expr))) + return; + while (TREE_CODE (expr) == COMPOUND_EXPR) + { + expr = TREE_OPERAND (expr, 1); + if (EXPR_HAS_LOCATION (expr)) + loc = EXPR_LOCATION (expr); + } + if (TREE_CODE (expr) != CALL_EXPR) + return; + tree fn = CALL_EXPR_FN (expr); + if (!fn) + return; + tree attr; + if (TREE_CODE (fn) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL + && (attr = lookup_attribute ("nodiscard", + DECL_ATTRIBUTES (TREE_OPERAND (fn, 0))))) + { + fn = TREE_OPERAND (fn, 0); + tree args = TREE_VALUE (attr); + if (args) + args = TREE_VALUE (args); + auto_diagnostic_group d; + int warned; + if (args) + warned = warning_at (loc, OPT_Wunused_result, + "ignoring return value of %qD, declared with " + "attribute %<nodiscard%>: %E", fn, args); + else + warned = warning_at (loc, OPT_Wunused_result, + "ignoring return value of %qD, declared with " + "attribute %<nodiscard%>", fn); + if (warned) + inform (DECL_SOURCE_LOCATION (fn), "declared here"); + } + else + { + tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))); + attr = lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype)); + if (!attr) + return; + tree args = TREE_VALUE (attr); + if (args) + args = TREE_VALUE (args); + auto_diagnostic_group d; + int warned; + if (args) + warned = warning_at (loc, OPT_Wunused_result, + "ignoring return value of type %qT, declared " + "with attribute %<nodiscard%>: %E", + rettype, args); + else + warned = warning_at (loc, OPT_Wunused_result, + "ignoring return value of type %qT, declared " + "with attribute %<nodiscard%>", rettype); + if (warned) + { + if (TREE_CODE (fn) == ADDR_EXPR) + { + fn = TREE_OPERAND (fn, 0); + if (TREE_CODE (fn) == FUNCTION_DECL) + inform (DECL_SOURCE_LOCATION (fn), + "in call to %qD, declared here", fn); + } + } + } +} + /* Return a compound expression that performs two expressions and returns the value of the second of them. @@ -5561,6 +5640,8 @@ build_compound_expr (location_t loc, tree expr1, tree expr2) else if (warn_unused_value) warn_if_unused_value (expr1, loc); + maybe_warn_nodiscard (loc, expr1); + if (expr2 == error_mark_node) return error_mark_node; @@ -6194,16 +6275,9 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, "enum conversion in assignment is invalid in C++"); } - /* If the lhs is atomic, remove that qualifier. */ - if (is_atomic_op) - { - lhstype = build_qualified_type (lhstype, - (TYPE_QUALS (lhstype) - & ~TYPE_QUAL_ATOMIC)); - olhstype = build_qualified_type (olhstype, - (TYPE_QUALS (lhstype) - & ~TYPE_QUAL_ATOMIC)); - } + /* Remove qualifiers. */ + lhstype = build_qualified_type (lhstype, TYPE_UNQUALIFIED); + olhstype = build_qualified_type (olhstype, TYPE_UNQUALIFIED); /* Convert new value to destination type. Fold it first, then restore any excess precision information, for the sake of @@ -6500,7 +6574,7 @@ inform_for_arg (tree fundecl, location_t ploc, int parmnum, tree expected_type, tree actual_type) { location_t loc; - if (fundecl && !DECL_IS_BUILTIN (fundecl)) + if (fundecl && !DECL_IS_UNDECLARED_BUILTIN (fundecl)) loc = get_fndecl_argument_location (fundecl, parmnum - 1); else loc = ploc; @@ -6750,7 +6824,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, if (pedwarn (expr_loc, OPT_Wc___compat, "enum conversion when " "passing argument %d of %qE is invalid in C++", parmnum, rname)) - inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) + inform ((fundecl && !DECL_IS_UNDECLARED_BUILTIN (fundecl)) ? DECL_SOURCE_LOCATION (fundecl) : expr_loc, "expected %qT but argument is of type %qT", type, rhstype); @@ -7161,7 +7235,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, 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_BUILTIN (rname)) + if (TREE_CODE (rname) != FUNCTION_DECL + || !DECL_IS_UNDECLARED_BUILTIN (rname)) warning_at (location, OPT_Wscalar_storage_order, "passing argument %d of %qE from incompatible " "scalar storage order", parmnum, rname); @@ -8314,13 +8389,13 @@ finish_init (void) { struct constructor_stack *q = constructor_stack; constructor_stack = q->next; - free (q); + XDELETE (q); } gcc_assert (!constructor_range_stack); /* Pop back to the data of the outer initializer (if any). */ - free (spelling_base); + XDELETE (spelling_base); constructor_decl = p->decl; require_constant_value = p->require_constant_value; @@ -8333,7 +8408,7 @@ finish_init (void) spelling_size = p->spelling_size; constructor_top_level = p->top_level; initializer_stack = p->next; - free (p); + XDELETE (p); } /* Call here when we see the initializer is surrounded by braces. @@ -8864,7 +8939,7 @@ pop_init_level (location_t loc, int implicit, RESTORE_SPELLING_DEPTH (constructor_depth); constructor_stack = p->next; - free (p); + XDELETE (p); if (ret.value == NULL_TREE && constructor_stack == 0) ret.value = error_mark_node; @@ -10586,10 +10661,6 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, TREE_VALUE (tail) = input; } - /* ASMs with labels cannot have outputs. This should have been - enforced by the parser. */ - gcc_assert (outputs == NULL || labels == NULL); - args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels); /* asm statements without outputs, including simple ones, are treated @@ -11072,6 +11143,9 @@ c_finish_bc_stmt (location_t loc, tree label, bool is_break) static void emit_side_effect_warnings (location_t loc, tree expr) { + maybe_warn_nodiscard (loc, expr); + if (!warn_unused_value) + return; if (expr == error_mark_node) ; else if (!TREE_SIDE_EFFECTS (expr)) @@ -11127,7 +11201,7 @@ c_process_expr_stmt (location_t loc, tree expr) Warnings for statement expressions will be emitted later, once we figure out which is the result. */ if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list) - && warn_unused_value) + && (warn_unused_value || warn_unused_result)) emit_side_effect_warnings (EXPR_LOC_OR_LOC (expr, loc), expr); exprv = expr; @@ -11221,7 +11295,7 @@ c_finish_stmt_expr (location_t loc, tree body) /* If we're supposed to generate side effects warnings, process all of the statements except the last. */ - if (warn_unused_value) + if (warn_unused_value || warn_unused_result) { for (tree_stmt_iterator i = tsi_start (last); tsi_stmt (i) != tsi_stmt (l); tsi_next (&i)) @@ -12184,8 +12258,8 @@ build_binary_op (location_t location, enum tree_code code, result_type = common_pointer_type (type0, type1); if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) != !COMPLETE_TYPE_P (TREE_TYPE (type1))) - pedwarn (location, 0, - "comparison of complete and incomplete pointers"); + pedwarn_c99 (location, OPT_Wpedantic, + "comparison of complete and incomplete pointers"); else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) pedwarn (location, OPT_Wpedantic, "ISO C forbids " "ordered comparisons of pointers to functions"); @@ -12242,6 +12316,7 @@ build_binary_op (location_t location, enum tree_code code, } if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE) + && current_function_decl != NULL_TREE && sanitize_flags_p (SANITIZE_POINTER_COMPARE)) { op0 = save_expr (op0); @@ -13501,11 +13576,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) 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) - { - gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH - : GOMP_MAP_ALWAYS_POINTER; - OMP_CLAUSE_SET_MAP_KIND (c2, k); - } + OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH); else OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER); if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER @@ -13795,6 +13866,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) /* 1 if normal/task reduction has been seen, -1 if inscan reduction has been seen, -2 if mixed inscan/normal reduction diagnosed. */ int reduction_seen = 0; + bool allocate_seen = false; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); @@ -14344,6 +14416,29 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bitmap_set_bit (&oacc_reduction_head, DECL_UID (t)); break; + case OMP_CLAUSE_ALLOCATE: + t = OMP_CLAUSE_DECL (c); + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %<allocate%> clause", t); + remove = true; + } + else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "%qE appears more than once in %<allocate%> clauses", + t); + remove = true; + } + else + { + bitmap_set_bit (&aligned_head, DECL_UID (t)); + if (!OMP_CLAUSE_ALLOCATE_COMBINED (c)) + allocate_seen = true; + } + break; + case OMP_CLAUSE_DEPEND: t = OMP_CLAUSE_DECL (c); if (t == NULL_TREE) @@ -14604,7 +14699,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) { - if (bitmap_bit_p (&map_field_head, DECL_UID (t))) + if (bitmap_bit_p (&map_field_head, DECL_UID (t)) + || (ort == C_ORT_OMP + && bitmap_bit_p (&map_head, DECL_UID (t)))) break; } } @@ -14673,7 +14770,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else bitmap_set_bit (&generic_head, DECL_UID (t)); } - else if (bitmap_bit_p (&map_head, DECL_UID (t))) + else if (bitmap_bit_p (&map_head, DECL_UID (t)) + && (ort != C_ORT_OMP + || !bitmap_bit_p (&map_field_head, DECL_UID (t)))) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) error_at (OMP_CLAUSE_LOCATION (c), @@ -14687,7 +14786,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; } else if (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&firstprivate_head, DECL_UID (t))) + && ort == C_ORT_ACC) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); + remove = true; + } + else if (bitmap_bit_p (&firstprivate_head, DECL_UID (t))) { if (ort == C_ORT_ACC) error_at (OMP_CLAUSE_LOCATION (c), @@ -15041,10 +15146,40 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) reduction_seen = -2; } - if (linear_variable_step_check || reduction_seen == -2) + if (linear_variable_step_check || reduction_seen == -2 || allocate_seen) for (pc = &clauses, c = clauses; c ; c = *pc) { bool remove = false; + if (allocate_seen) + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_REDUCTION: + case OMP_CLAUSE_IN_REDUCTION: + case OMP_CLAUSE_TASK_REDUCTION: + if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF) + { + t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0); + if (TREE_CODE (t) == POINTER_PLUS_EXPR) + t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == ADDR_EXPR + || TREE_CODE (t) == INDIRECT_REF) + t = TREE_OPERAND (t, 0); + if (DECL_P (t)) + bitmap_clear_bit (&aligned_head, DECL_UID (t)); + break; + } + /* FALLTHRU */ + case OMP_CLAUSE_PRIVATE: + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_LASTPRIVATE: + case OMP_CLAUSE_LINEAR: + if (DECL_P (OMP_CLAUSE_DECL (c))) + bitmap_clear_bit (&aligned_head, + DECL_UID (OMP_CLAUSE_DECL (c))); + break; + default: + break; + } if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c) && !bitmap_bit_p (&map_head, @@ -15056,7 +15191,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) OMP_CLAUSE_LINEAR_STEP (c)); remove = true; } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && reduction_seen == -2) OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; if (remove) @@ -15065,6 +15201,25 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); } + if (allocate_seen) + for (pc = &clauses, c = clauses; c ; c = *pc) + { + bool remove = false; + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE + && !OMP_CLAUSE_ALLOCATE_COMBINED (c) + && bitmap_bit_p (&aligned_head, DECL_UID (OMP_CLAUSE_DECL (c)))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD specified in %<allocate%> clause but not in " + "an explicit privatization clause", OMP_CLAUSE_DECL (c)); + remove = true; + } + if (remove) + *pc = OMP_CLAUSE_CHAIN (c); + else + pc = &OMP_CLAUSE_CHAIN (c); + } + if (nogroup_seen && reduction_seen) { error_at (OMP_CLAUSE_LOCATION (*nogroup_seen), diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index 5c0ed82..473cb90 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -1700,6 +1700,8 @@ c_parser_gimple_postfix_expression (gimple_parser &parser) expr.set_error (); break; } + if (expr.value == error_mark_node) + return expr; return c_parser_gimple_postfix_expression_after_primary (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr); } |