diff options
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/c/c-decl.cc | 70 | ||||
-rw-r--r-- | gcc/c/c-parser.cc | 38 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 1 |
4 files changed, 103 insertions, 29 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 241e71b..6f51dd9 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,26 @@ +2025-10-21 Martin Uecker <uecker@tugraz.at> + + * c-decl.cc (build_array_declarator): Remove error. + (grokgenassoc): New function. + (grokdeclarator): Add error. + * c-parser.cc (c_parser_generic_selection): Use grokgenassoc. + * c-tree.h (grokgenassoc): Add prototype. + +2025-10-21 Paul-Antoine Arras <parras@baylibre.com> + + PR c/120180 + PR fortran/122306 + * c-parser.cc (c_parser_pragma): Accept a subset of non-executable + OpenMP directives in intervening code. + (c_parser_omp_error): Reject 'error at(execution)' in intervening code. + (c_parser_omp_metadirective): Return early if only one selector matches + and it resolves to 'omp nothing'. + +2025-10-21 Tobias Burnus <tburnus@baylibre.com> + + * c-parser.cc (c_parser_omp_assumption_clauses): Switch to + 'unknown' not 'invalid' directive name for end directives. + 2025-10-08 Joseph Myers <josmyers@redhat.com> * c-typeck.cc (in_generic, save_maybe_used, restore_maybe_used): diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 4a940d5..061892a 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -71,7 +71,8 @@ enum decl_context FUNCDEF, /* Function definition */ PARM, /* Declaration of parm before function body */ FIELD, /* Declaration inside struct or union */ - TYPENAME}; /* Typename (inside cast or sizeof) */ + TYPENAME, /* Typename (inside cast or sizeof) */ + GENERIC_ASSOC }; /* Typename in generic association */ /* States indicating how grokdeclarator() should handle declspecs marked with __attribute__((deprecated)) or __attribute__((unavailable)). @@ -5456,19 +5457,11 @@ build_array_declarator (location_t loc, "ISO C90 does not support %<static%> or type " "qualifiers in parameter array declarators"); if (vla_unspec_p) - pedwarn_c90 (loc, OPT_Wpedantic, - "ISO C90 does not support %<[*]%> array declarators"); - if (vla_unspec_p) { - if (!current_scope->parm_flag) - { - /* C99 6.7.5.2p4 */ - error_at (loc, "%<[*]%> not allowed in other than " - "function prototype scope"); - declarator->u.array.vla_unspec_p = false; - return NULL; - } - current_scope->had_vla_unspec = true; + pedwarn_c90 (loc, OPT_Wpedantic, + "ISO C90 does not support %<[*]%> array declarators"); + if (current_scope->parm_flag) + current_scope->had_vla_unspec = true; } return declarator; } @@ -5574,6 +5567,29 @@ groktypename (struct c_type_name *type_name, tree *expr, return type; } + +/* Decode a "typename", such as "int **", returning a ..._TYPE node, + as for groktypename but setting the context to GENERIC_ASSOC. */ + +tree +grokgenassoc (struct c_type_name *type_name) +{ + tree type; + tree attrs = type_name->specs->attrs; + + type_name->specs->attrs = NULL_TREE; + + type = grokdeclarator (type_name->declarator, type_name->specs, GENERIC_ASSOC, + false, NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL); + + /* Apply attributes. */ + attrs = c_warn_type_attributes (type, attrs); + decl_attributes (&type, attrs, 0); + + return type; +} + + /* Looks up the most recent pushed declaration corresponding to DECL. */ static tree @@ -6772,6 +6788,7 @@ build_arg_spec_attribute (tree type, bool static_p, tree attrs) or before a function body). Make a PARM_DECL, or return void_type_node. TYPENAME if for a typename (in a cast or sizeof). Don't make a DECL node; just return the ..._TYPE node. + GENERIC_ASSOC for typenames in a generic association. FIELD for a struct or union field; make a FIELD_DECL. INITIALIZED is true if the decl has an initializer. WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node @@ -6908,6 +6925,7 @@ grokdeclarator (const struct c_declarator *declarator, { gcc_assert (decl_context == PARM || decl_context == TYPENAME + || decl_context == GENERIC_ASSOC || (decl_context == FIELD && declarator->kind == cdk_id)); gcc_assert (!initialized); @@ -7481,14 +7499,6 @@ grokdeclarator (const struct c_declarator *declarator, itype = build_index_type (NULL_TREE); } - if (array_parm_vla_unspec_p) - { - /* C99 6.7.5.2p4 */ - if (decl_context == TYPENAME) - warning (0, "%<[*]%> not in a declaration"); - size_varies = true; - } - /* Complain about arrays of incomplete types. */ if (!COMPLETE_TYPE_P (type)) { @@ -7527,6 +7537,22 @@ grokdeclarator (const struct c_declarator *declarator, type = c_build_array_type (type, itype); } + if (array_parm_vla_unspec_p) + { + /* C99 6.7.5.2p4 */ + if (decl_context == TYPENAME) + warning (0, "%<[*]%> not in a declaration"); + else if (decl_context != GENERIC_ASSOC + && decl_context != PARM + && decl_context != FIELD) + { + error ("%<[*]%> not allowed in other than function prototype scope " + "or generic association"); + type = error_mark_node; + } + size_varies = true; + } + if (type != error_mark_node) { /* The GCC extension for zero-length arrays differs from @@ -7898,7 +7924,7 @@ grokdeclarator (const struct c_declarator *declarator, /* If this is a type name (such as, in a cast or sizeof), compute the type and return it now. */ - if (decl_context == TYPENAME) + if (decl_context == TYPENAME || decl_context == GENERIC_ASSOC) { /* Note that the grammar rejects storage classes in typenames and fields. */ diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index ea0294f..56fb0be 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -11240,7 +11240,7 @@ c_parser_generic_selection (c_parser *parser) c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return error_expr; } - assoc.type = groktypename (type_name, NULL, NULL); + assoc.type = grokgenassoc (type_name); if (assoc.type == error_mark_node) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); @@ -15787,11 +15787,15 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p, gcc_assert (id != PRAGMA_NONE); if (parser->omp_for_parse_state && parser->omp_for_parse_state->in_intervening_code - && id >= PRAGMA_OMP__START_ - && id <= PRAGMA_OMP__LAST_) - { - error_at (input_location, - "intervening code must not contain OpenMP directives"); + && id >= PRAGMA_OMP__START_ && id <= PRAGMA_OMP__LAST_ + /* Allow a safe subset of non-executable directives. See classification in + array c_omp_directives. */ + && id != PRAGMA_OMP_METADIRECTIVE && id != PRAGMA_OMP_NOTHING + && id != PRAGMA_OMP_ASSUME && id != PRAGMA_OMP_ERROR) + { + error_at ( + input_location, + "intervening code must not contain executable OpenMP directives"); parser->omp_for_parse_state->fail = true; c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); return false; @@ -29334,6 +29338,14 @@ c_parser_omp_error (c_parser *parser, enum pragma_context context) "may only be used in compound statements"); return true; } + if (parser->omp_for_parse_state + && parser->omp_for_parse_state->in_intervening_code) + { + error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause " + "may not be used in intervening code"); + parser->omp_for_parse_state->fail = true; + return true; + } tree fndecl = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR : BUILT_IN_GOMP_WARNING); @@ -29480,6 +29492,7 @@ c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume) directive[1], directive[2]); if (dir + && dir->id != PRAGMA_OMP_END && (dir->kind == C_OMP_DIR_DECLARATIVE || dir->kind == C_OMP_DIR_INFORMATIONAL || dir->kind == C_OMP_DIR_META)) @@ -29863,6 +29876,17 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p) } c_parser_skip_to_pragma_eol (parser); + /* If only one selector matches and it evaluates to 'omp nothing', no need to + proceed. */ + if (ctxs.length () == 1) + { + tree ctx = ctxs[0]; + if (ctx == NULL_TREE + || (omp_context_selector_matches (ctx, NULL_TREE, false) == 1 + && directive_tokens[0].pragma_kind == PRAGMA_OMP_NOTHING)) + return; + } + if (!default_seen) { /* Add a default clause that evaluates to 'omp nothing'. */ @@ -29943,7 +29967,7 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p) if (standalone_body == NULL_TREE) { standalone_body = push_stmt_list (); - c_parser_statement (parser, if_p); + c_parser_statement (parser, if_p); // TODO skip this standalone_body = pop_stmt_list (standalone_body); } else diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 162add0..f367cda 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -713,6 +713,7 @@ extern struct c_arg_info *get_parm_info (bool, tree); extern tree grokfield (location_t, struct c_declarator *, struct c_declspecs *, tree, tree *, tree *); extern tree groktypename (struct c_type_name *, tree *, bool *); +extern tree grokgenassoc (struct c_type_name *); extern tree grokparm (const struct c_parm *, tree *); extern tree implicitly_declare (location_t, tree); extern void keep_next_level (void); |