aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog117
-rw-r--r--gcc/c/c-decl.cc203
-rw-r--r--gcc/c/c-objc-common.cc5
-rw-r--r--gcc/c/c-objc-common.h12
-rw-r--r--gcc/c/c-parser.cc471
-rw-r--r--gcc/c/c-tree.h12
-rw-r--r--gcc/c/c-typeck.cc149
7 files changed, 886 insertions, 83 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index b7cdd11..7f5b0b8 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,120 @@
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ * c-typeck.cc (composite_type_internal,composite_type): Move
+ checking assertions.
+
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ PR c/116892
+ * c-decl.cc (finish_enum): Propagate TYPE_PACKED.
+
+2025-06-02 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_context_selector): Call
+ convert_lvalue_to_rvalue and c_objc_common_truthvalue_conversion
+ on the expression for OMP_TRAIT_PROPERTY_BOOL_EXPR.
+
+2025-06-01 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120380
+ * c-objc-common.cc (get_aka_type): Ignore attributes for tagged types.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120354
+ * c-decl.cc (finish_struct): Or the results for TYPE_INCLUDES_FLEXARRAY.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120353
+ * c-decl.cc (finish_struct): Copy TYPE_INCLUDES_FLEXARRAY marking
+ to all the variant types of the current structure type.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+
+ * c-decl.cc (c_omp_mapper_id, c_omp_mapper_decl, c_omp_mapper_lookup,
+ c_omp_extract_mapper_directive, c_omp_map_array_section,
+ c_omp_scan_mapper_bindings_r, c_omp_scan_mapper_bindings): New
+ functions.
+ * c-objc-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES,
+ LANG_HOOKS_OMP_MAPPER_LOOKUP, LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE,
+ LANG_HOOKS_OMP_MAP_ARRAY_SECTION): Define langhooks for C.
+ * c-parser.cc (c_parser_omp_clause_map): Add declare_mapper_p
+ parameter; handle mapper modifier.
+ (c_parser_omp_all_clauses): Update call to c_parser_omp_clause_map.
+ (c_parser_omp_target): Instantiate explicit mappers and record bindings
+ for implicit mappers.
+ (c_parser_omp_declare_mapper): Parse "declare mapper" directives.
+ (c_parser_omp_declare): Support "declare mapper".
+ (c_parser_omp_declare_reduction): Use inform not error_at.
+ * c-tree.h (c_omp_finish_mapper_clauses, c_omp_mapper_lookup,
+ c_omp_extract_mapper_directive, c_omp_map_array_section,
+ c_omp_mapper_id, c_omp_mapper_decl, c_omp_scan_mapper_bindings,
+ c_omp_instantiate_mappers): Add prototypes.
+ * c-typeck.cc (c_finish_omp_clauses): Handle GOMP_MAP_PUSH_MAPPER_NAME
+ and GOMP_MAP_POP_MAPPER_NAME.
+ (c_omp_finish_mapper_clauses): New function (langhook).
+
+2025-05-30 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120381
+ * c-typeck.cc (composite_type_internal): Stop recursion for
+ swapped pairs.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * c-parser.cc (c_parser_skip_to_closing_brace): New, copied from
+ the equivalent function in the C++ front end.
+ (c_parser_skip_to_end_of_block_or_statement): Pass false to
+ the error flag.
+ (c_parser_omp_context_selector): Immediately return error_mark_node
+ after giving an error that the integer trait property is invalid,
+ similarly to C++ front end.
+ (c_parser_omp_context_selector_specification): Likewise handle
+ error return from c_parser_omp_context_selector similarly to C++.
+ (c_parser_omp_metadirective): Do not call
+ c_parser_skip_to_end_of_block_or_statement after an error.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ PR c/120180
+ * c-parser.cc (c_parser_omp_metadirective): Only consume the
+ token if it is the expected close paren.
+
+2025-05-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/117025
+ * c-parser.cc (c_parser_sizeof_or_countof_expression): Use
+ C2Y rather than C23 in pedwarn_c23.
+
+2025-05-27 Alejandro Colomar <alx@kernel.org>
+
+ PR c/117025
+ * c-parser.cc (c_parser_sizeof_or_countof_expression):
+ Add -Wpedantic diagnostic for _Countof in <= C23 mode.
+
+2025-05-27 Alejandro Colomar <alx@kernel.org>
+ Martin Uecker <uecker@tugraz.at>
+
+ PR c/117025
+ * c-tree.h (in_countof): Add global variable declaration.
+ (c_expr_countof_expr): Add function prototype.
+ (c_expr_countof_type): Add function prototype.
+ * c-decl.cc (start_struct, finish_struct): Add support for
+ _Countof.
+ (start_enum, finish_enum): Add support for _Countof.
+ * c-parser.cc (c_parser_sizeof_expression): New macro.
+ (c_parser_countof_expression): New macro.
+ (c_parser_sizeof_or_countof_expression): Rename function and add
+ support for _Countof.
+ (c_parser_unary_expression): Add RID_COUNTOF entry.
+ * c-typeck.cc (in_countof): Add global variable.
+ (build_external_ref): Add support for _Countof.
+ (record_maybe_used_decl): Add support for _Countof.
+ (pop_maybe_used): Add support for _Countof.
+ (is_top_array_vla): New function.
+ (c_expr_countof_expr, c_expr_countof_type): New functions.
+
2025-05-02 Jakub Jelinek <jakub@redhat.com>
PR c/120057
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index ad66d7d..2b0bd66 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -8943,12 +8943,14 @@ start_struct (location_t loc, enum tree_code code, tree name,
within a statement expr used within sizeof, et. al. This is not
terribly serious as C++ doesn't permit statement exprs within
sizeof anyhow. */
- if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+ if (warn_cxx_compat
+ && (in_sizeof || in_typeof || in_alignof || in_countof))
warning_at (loc, OPT_Wc___compat,
"defining type in %qs expression is invalid in C++",
- (in_sizeof
- ? "sizeof"
- : (in_typeof ? "typeof" : "alignof")));
+ (in_sizeof ? "sizeof"
+ : in_typeof ? "typeof"
+ : in_alignof ? "alignof"
+ : "_Countof"));
if (in_underspecified_init)
error_at (loc, "%qT defined in underspecified object initializer", ref);
@@ -9647,15 +9649,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
/* Set TYPE_INCLUDES_FLEXARRAY for the context of x, t.
- when x is an array and is the last field. */
+ when x is an array and is the last field.
+ There is only one last_field for a structure type, but there might
+ be multiple last_fields for a union type, therefore we should ORed
+ the result for multiple last_fields. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
+ |= is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
/* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t
when x is an union or record and is the last field. */
else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
+ |= is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
if (warn_flex_array_member_not_at_end
&& !is_last_field
@@ -9891,6 +9896,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
C_TYPE_VARIABLY_MODIFIED (x) = C_TYPE_VARIABLY_MODIFIED (t);
C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE;
+ TYPE_INCLUDES_FLEXARRAY (x) = TYPE_INCLUDES_FLEXARRAY (t);
}
/* Update type location to the one of the definition, instead of e.g.
@@ -9923,7 +9929,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
struct_types. */
if (warn_cxx_compat
&& struct_parse_info != NULL
- && !in_sizeof && !in_typeof && !in_alignof)
+ && !in_sizeof && !in_typeof && !in_alignof && !in_countof)
struct_parse_info->struct_types.safe_push (t);
}
@@ -10097,12 +10103,14 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name,
/* FIXME: This will issue a warning for a use of a type defined
within sizeof in a statement expr. This is not terribly serious
as C++ doesn't permit statement exprs within sizeof anyhow. */
- if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+ if (warn_cxx_compat
+ && (in_sizeof || in_typeof || in_alignof || in_countof))
warning_at (loc, OPT_Wc___compat,
"defining type in %qs expression is invalid in C++",
- (in_sizeof
- ? "sizeof"
- : (in_typeof ? "typeof" : "alignof")));
+ (in_sizeof ? "sizeof"
+ : in_typeof ? "typeof"
+ : in_alignof ? "alignof"
+ : "_Countof"));
if (in_underspecified_init)
error_at (loc, "%qT defined in underspecified object initializer",
@@ -10285,6 +10293,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
ENUM_UNDERLYING_TYPE (tem) = ENUM_UNDERLYING_TYPE (enumtype);
+ TYPE_PACKED (tem) = TYPE_PACKED (enumtype);
}
/* Finish debugging output for this type. */
@@ -10296,7 +10305,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
struct_types. */
if (warn_cxx_compat
&& struct_parse_info != NULL
- && !in_sizeof && !in_typeof && !in_alignof)
+ && !in_sizeof && !in_typeof && !in_alignof && !in_countof)
struct_parse_info->struct_types.safe_push (enumtype);
/* Check for consistency with previous definition */
@@ -13819,6 +13828,174 @@ c_check_omp_declare_reduction_r (tree *tp, int *, void *data)
return NULL_TREE;
}
+/* Return identifier to look up for omp declare mapper. */
+
+tree
+c_omp_mapper_id (tree mapper_id)
+{
+ const char *p = NULL;
+
+ const char prefix[] = "omp declare mapper ";
+
+ if (mapper_id == NULL_TREE)
+ p = "<default>";
+ else if (TREE_CODE (mapper_id) == IDENTIFIER_NODE)
+ p = IDENTIFIER_POINTER (mapper_id);
+ else
+ return error_mark_node;
+
+ size_t lenp = sizeof (prefix);
+ size_t len = strlen (p);
+ char *name = XALLOCAVEC (char, lenp + len);
+ memcpy (name, prefix, lenp - 1);
+ memcpy (name + lenp - 1, p, len + 1);
+ return get_identifier (name);
+}
+
+/* Lookup MAPPER_ID in the current scope, or create an artificial
+ VAR_DECL, bind it into the current scope and return it. */
+
+tree
+c_omp_mapper_decl (tree mapper_id)
+{
+ struct c_binding *b = I_SYMBOL_BINDING (mapper_id);
+ if (b != NULL && B_IN_CURRENT_SCOPE (b))
+ return b->decl;
+
+ tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ mapper_id, integer_type_node);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ TREE_PUBLIC (decl) = 0;
+ bind (mapper_id, decl, current_scope, true, false, BUILTINS_LOCATION);
+ return decl;
+}
+
+/* Lookup MAPPER_ID in the first scope where it has entry for TYPE. */
+
+tree
+c_omp_mapper_lookup (tree mapper_id, tree type)
+{
+ if (!RECORD_OR_UNION_TYPE_P (type))
+ return NULL_TREE;
+
+ mapper_id = c_omp_mapper_id (mapper_id);
+
+ struct c_binding *b = I_SYMBOL_BINDING (mapper_id);
+ while (b)
+ {
+ tree t;
+ for (t = DECL_INITIAL (b->decl); t; t = TREE_CHAIN (t))
+ if (comptypes (TREE_PURPOSE (t), type))
+ return TREE_VALUE (t);
+ b = b->shadowed;
+ }
+ return NULL_TREE;
+}
+
+/* For C, we record a pointer to the mapper itself without wrapping it in an
+ artificial function or similar. So, just return it. */
+
+tree
+c_omp_extract_mapper_directive (tree mapper)
+{
+ return mapper;
+}
+
+/* For now we can handle singleton OMP_ARRAY_SECTIONs with custom mappers, but
+ nothing more complicated. */
+
+tree
+c_omp_map_array_section (location_t loc, tree t)
+{
+ tree low = TREE_OPERAND (t, 1);
+ tree len = TREE_OPERAND (t, 2);
+
+ if (len && integer_onep (len))
+ {
+ t = TREE_OPERAND (t, 0);
+
+ if (!low)
+ low = integer_zero_node;
+
+ t = build_array_ref (loc, t, low);
+ }
+
+ return t;
+}
+
+/* Helper function for below function. */
+
+static tree
+c_omp_scan_mapper_bindings_r (tree *tp, int *walk_subtrees, void *ptr)
+{
+ tree t = *tp;
+ omp_mapper_list<tree> *mlist = (omp_mapper_list<tree> *) ptr;
+ tree aggr_type = NULL_TREE;
+
+ if (TREE_CODE (t) == SIZEOF_EXPR
+ || TREE_CODE (t) == ALIGNOF_EXPR)
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (t) == OMP_CLAUSE)
+ return NULL_TREE;
+
+ if (TREE_CODE (t) == COMPONENT_REF
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
+ aggr_type = TREE_TYPE (TREE_OPERAND (t, 0));
+ else if ((TREE_CODE (t) == VAR_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == RESULT_DECL)
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
+ aggr_type = TREE_TYPE (t);
+
+ if (aggr_type)
+ {
+ tree mapper_fn = c_omp_mapper_lookup (NULL_TREE, aggr_type);
+ if (mapper_fn)
+ mlist->add_mapper (NULL_TREE, aggr_type, mapper_fn);
+ }
+
+ return NULL_TREE;
+}
+
+/* Scan an offload region's body, and record uses of struct- or union-typed
+ variables. Add _mapper_binding_ fake clauses to *CLAUSES_PTR. */
+
+void
+c_omp_scan_mapper_bindings (location_t loc, tree *clauses_ptr, tree body)
+{
+ hash_set<omp_name_type<tree>> seen_types;
+ auto_vec<tree> mappers;
+ omp_mapper_list<tree> mlist (&seen_types, &mappers);
+
+ walk_tree_without_duplicates (&body, c_omp_scan_mapper_bindings_r, &mlist);
+
+ unsigned int i;
+ tree mapper;
+ FOR_EACH_VEC_ELT (mappers, i, mapper)
+ c_omp_find_nested_mappers (&mlist, mapper);
+
+ FOR_EACH_VEC_ELT (mappers, i, mapper)
+ {
+ if (mapper == error_mark_node)
+ continue;
+ tree mapper_name = OMP_DECLARE_MAPPER_ID (mapper);
+ tree decl = OMP_DECLARE_MAPPER_DECL (mapper);
+
+ tree c = build_omp_clause (loc, OMP_CLAUSE__MAPPER_BINDING_);
+ OMP_CLAUSE__MAPPER_BINDING__ID (c) = mapper_name;
+ OMP_CLAUSE__MAPPER_BINDING__DECL (c) = decl;
+ OMP_CLAUSE__MAPPER_BINDING__MAPPER (c) = mapper;
+
+ OMP_CLAUSE_CHAIN (c) = *clauses_ptr;
+ *clauses_ptr = c;
+ }
+}
bool
c_check_in_current_scope (tree decl)
diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc
index 2016eae..d574bc7 100644
--- a/gcc/c/c-objc-common.cc
+++ b/gcc/c/c-objc-common.cc
@@ -216,6 +216,11 @@ get_aka_type (tree type)
return canonical ? canonical : type;
}
}
+ /* For tagged types ignore attributes because they will otherwise
+ be ignored later causing a warning inside diagnostics which leads
+ to an ICE. */
+ if (RECORD_OR_UNION_TYPE_P (type) || TREE_CODE (type) == ENUMERAL_TYPE)
+ return build_qualified_type (result, TYPE_QUALS (type));
return build_type_attribute_qual_variant (result, TYPE_ATTRIBUTES (type),
TYPE_QUALS (type));
}
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index 84bd357..84f6fd3 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -137,6 +137,18 @@ static const scoped_attribute_specs *const c_objc_attribute_table[] =
#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP c_omp_clause_copy_ctor
+#undef LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES
+#define LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES c_omp_finish_mapper_clauses
+
+#undef LANG_HOOKS_OMP_MAPPER_LOOKUP
+#define LANG_HOOKS_OMP_MAPPER_LOOKUP c_omp_mapper_lookup
+
+#undef LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE
+#define LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE c_omp_extract_mapper_directive
+
+#undef LANG_HOOKS_OMP_MAP_ARRAY_SECTION
+#define LANG_HOOKS_OMP_MAP_ARRAY_SECTION c_omp_map_array_section
+
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_var_mod_p
#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 8a63dc5..85580c5 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -77,7 +77,7 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "c-family/c-ubsan.h"
#include "gcc-urlifier.h"
-
+
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
In finish_decl(), if the decl is static, has incomplete
@@ -1420,6 +1420,51 @@ c_parser_skip_to_end_of_parameter (c_parser *parser)
parser->error = false;
}
+/* Skip tokens until a non-nested closing curly brace is the next
+ token, or there are no more tokens. Return true in the first case,
+ false otherwise. */
+
+static bool
+c_parser_skip_to_closing_brace (c_parser *parser)
+{
+ unsigned nesting_depth = 0;
+
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+
+ switch (token->type)
+ {
+ case CPP_PRAGMA_EOL:
+ if (!parser->in_pragma)
+ break;
+ /* FALLTHRU */
+ case CPP_EOF:
+ /* If we've run out of tokens, stop. */
+ return false;
+
+ case CPP_CLOSE_BRACE:
+ /* If the next token is a non-nested `}', then we have reached
+ the end of the current block. */
+ if (nesting_depth-- == 0)
+ return true;
+ break;
+
+ case CPP_OPEN_BRACE:
+ /* If it the next token is a `{', then we are entering a new
+ block. Consume the entire block. */
+ ++nesting_depth;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Consume the token. */
+ c_parser_consume_token (parser);
+ }
+}
+
/* Expect to be at the end of the pragma directive and consume an
end of line marker. */
@@ -1535,7 +1580,7 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
here for secondary error recovery, after parser->error has
been cleared. */
c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
+ c_parser_skip_to_pragma_eol (parser, false);
parser->error = save_error;
continue;
@@ -1737,7 +1782,10 @@ static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
tree);
static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
static struct c_expr c_parser_unary_expression (c_parser *);
-static struct c_expr c_parser_sizeof_expression (c_parser *);
+static inline struct c_expr c_parser_sizeof_expression (c_parser *);
+static inline struct c_expr c_parser_countof_expression (c_parser *);
+static struct c_expr c_parser_sizeof_or_countof_expression (c_parser *,
+ enum rid);
static struct c_expr c_parser_alignof_expression (c_parser *);
static struct c_expr c_parser_postfix_expression (c_parser *);
static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
@@ -10452,9 +10500,13 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
++ unary-expression
-- unary-expression
unary-operator cast-expression
+ _Countof unary-expression
+ _Countof ( type-name )
sizeof unary-expression
sizeof ( type-name )
+ (_Countof is new in C2y.)
+
unary-operator: one of
& * + - ~ !
@@ -10572,6 +10624,8 @@ c_parser_unary_expression (c_parser *parser)
case CPP_KEYWORD:
switch (c_parser_peek_token (parser)->keyword)
{
+ case RID_COUNTOF:
+ return c_parser_countof_expression (parser);
case RID_SIZEOF:
return c_parser_sizeof_expression (parser);
case RID_ALIGNOF:
@@ -10610,22 +10664,46 @@ c_parser_unary_expression (c_parser *parser)
/* Parse a sizeof expression. */
-static struct c_expr
+static inline struct c_expr
c_parser_sizeof_expression (c_parser *parser)
{
+ return c_parser_sizeof_or_countof_expression (parser, RID_SIZEOF);
+}
+
+/* Parse a _Countof expression. */
+
+static inline struct c_expr
+c_parser_countof_expression (c_parser *parser)
+{
+ return c_parser_sizeof_or_countof_expression (parser, RID_COUNTOF);
+}
+
+/* Parse a sizeof or _Countof expression. */
+
+static struct c_expr
+c_parser_sizeof_or_countof_expression (c_parser *parser, enum rid rid)
+{
+ const char *op_name = (rid == RID_COUNTOF) ? "_Countof" : "sizeof";
struct c_expr expr;
struct c_expr result;
location_t expr_loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
+ gcc_assert (c_parser_next_token_is_keyword (parser, rid));
location_t start;
location_t finish = UNKNOWN_LOCATION;
start = c_parser_peek_token (parser)->location;
+ if (rid == RID_COUNTOF)
+ pedwarn_c23 (start, OPT_Wpedantic,
+ "ISO C does not support %qs before C2Y", op_name);
+
c_parser_consume_token (parser);
c_inhibit_evaluation_warnings++;
- in_sizeof++;
+ if (rid == RID_COUNTOF)
+ in_countof++;
+ else
+ in_sizeof++;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
&& c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
{
@@ -10646,7 +10724,7 @@ c_parser_sizeof_expression (c_parser *parser)
for parsing error; the parsing of the expression could have
called record_maybe_used_decl. */
expr.set_error ();
- goto sizeof_expr;
+ goto Xof_expr;
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
@@ -10654,31 +10732,45 @@ c_parser_sizeof_expression (c_parser *parser)
type_name,
expr_loc);
finish = expr.get_finish ();
- goto sizeof_expr;
+ goto Xof_expr;
}
/* sizeof ( type-name ). */
if (scspecs)
- error_at (expr_loc, "storage class specifier in %<sizeof%>");
+ error_at (expr_loc, "storage class specifier in %qs", op_name);
if (type_name->specs->alignas_p)
error_at (type_name->specs->locations[cdw_alignas],
- "alignment specified for type name in %<sizeof%>");
+ "alignment specified for type name in %qs", op_name);
c_inhibit_evaluation_warnings--;
- in_sizeof--;
- result = c_expr_sizeof_type (expr_loc, type_name);
+ if (rid == RID_COUNTOF)
+ {
+ in_countof--;
+ result = c_expr_countof_type (expr_loc, type_name);
+ }
+ else
+ {
+ in_sizeof--;
+ result = c_expr_sizeof_type (expr_loc, type_name);
+ }
}
else
{
expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_unary_expression (parser);
finish = expr.get_finish ();
- sizeof_expr:
+ Xof_expr:
c_inhibit_evaluation_warnings--;
- in_sizeof--;
+ if (rid == RID_COUNTOF)
+ in_countof--;
+ else
+ in_sizeof--;
mark_exp_read (expr.value);
if (TREE_CODE (expr.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error_at (expr_loc, "%<sizeof%> applied to a bit-field");
- result = c_expr_sizeof_expr (expr_loc, expr);
+ error_at (expr_loc, "%qs applied to a bit-field", op_name);
+ if (rid == RID_COUNTOF)
+ result = c_expr_countof_expr (expr_loc, expr);
+ else
+ result = c_expr_sizeof_expr (expr_loc, expr);
}
if (finish == UNKNOWN_LOCATION)
finish = start;
@@ -19941,11 +20033,11 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
always | close */
static tree
-c_parser_omp_clause_map (c_parser *parser, tree list)
+c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
- enum gomp_map_kind kind = GOMP_MAP_TOFROM;
tree nl, c;
+ enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
matching_parens parens;
if (!parens.require_open (parser))
@@ -19963,12 +20055,26 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
pos++;
+ else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, npos + 1)->type
+ == CPP_COMMA))
+ pos = npos + 1;
+ }
+
pos++;
}
int always_modifier = 0;
int close_modifier = 0;
int present_modifier = 0;
+ int mapper_modifier = 0;
+ tree mapper_name = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
c_token *tok = c_parser_peek_token (parser);
@@ -19989,6 +20095,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
always_modifier++;
+ c_parser_consume_token (parser);
}
else if (strcmp ("close", p) == 0)
{
@@ -19999,6 +20106,66 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
close_modifier++;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("mapper", p) == 0)
+ {
+ c_parser_consume_token (parser);
+
+ matching_parens mparens;
+ if (mparens.require_open (parser))
+ {
+ if (mapper_modifier)
+ {
+ c_parser_error (parser, "too many %<mapper%> modifiers");
+ /* Assume it's a well-formed mapper modifier, even if it
+ seems to be in the wrong place. */
+ c_parser_consume_token (parser);
+ mparens.require_close (parser);
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+
+ tok = c_parser_peek_token (parser);
+
+ switch (tok->type)
+ {
+ case CPP_NAME:
+ {
+ mapper_name = tok->value;
+ c_parser_consume_token (parser);
+ if (declare_mapper_p)
+ {
+ error_at (tok->location,
+ "in %<declare mapper%> directives, parameter "
+ "to %<mapper%> modifier must be %<default%>");
+ }
+ }
+ break;
+
+ case CPP_KEYWORD:
+ if (tok->keyword == RID_DEFAULT)
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Fallthrough. */
+
+ default:
+ error_at (tok->location,
+ "expected identifier or %<default%>");
+ return list;
+ }
+
+ if (!mparens.require_close (parser))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+
+ mapper_modifier++;
+ pos += 3;
+ }
}
else if (strcmp ("present", p) == 0)
{
@@ -20009,16 +20176,16 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
present_modifier++;
+ c_parser_consume_token (parser);
}
else
{
c_parser_error (parser, "%<map%> clause with map-type modifier other "
- "than %<always%>, %<close%> or %<present%>");
+ "than %<always%>, %<close%>, %<mapper%> or "
+ "%<present%>");
parens.skip_until_found_close (parser);
return list;
}
-
- c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_NAME)
@@ -20062,8 +20229,30 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
true);
+ tree last_new = NULL_TREE;
+
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ {
+ OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ last_new = c;
+ }
+
+ if (mapper_name)
+ {
+ tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = mapper_name;
+ OMP_CLAUSE_CHAIN (name) = nl;
+ nl = name;
+
+ gcc_assert (last_new);
+
+ name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = null_pointer_node;
+ OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
+ OMP_CLAUSE_CHAIN (last_new) = name;
+ }
parens.skip_until_found_close (parser);
return nl;
@@ -21432,7 +21621,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
c_name = "interop";
break;
case PRAGMA_OMP_CLAUSE_MAP:
- clauses = c_parser_omp_clause_map (parser, clauses);
+ clauses = c_parser_omp_clause_map (parser, clauses, false);
c_name = "map";
break;
case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
@@ -26251,7 +26440,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
- tree *pc = NULL, stmt, block;
+ tree *pc = NULL, stmt, block, body, clauses;
if (context != pragma_stmt && context != pragma_compound)
{
@@ -26406,10 +26595,9 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_CLAUSES (stmt)
- = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
- "#pragma omp target", false);
- for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
+ clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
+ "#pragma omp target", false);
+ for (tree c = clauses; 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);
@@ -26418,14 +26606,19 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
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);
+ clauses = c_omp_instantiate_mappers (clauses);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
+ c_omp_adjust_map_clauses (clauses, true);
- pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser, if_p));
+ body = c_parser_omp_structured_block (parser, if_p);
+
+ c_omp_scan_mapper_bindings (loc, &clauses, body);
+
+ add_stmt (body);
+ OMP_TARGET_CLAUSES (stmt) = clauses;
+ pc = &OMP_TARGET_CLAUSES (stmt);
OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
@@ -26773,20 +26966,31 @@ c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
break;
case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
case OMP_TRAIT_PROPERTY_BOOL_EXPR:
- t = c_parser_expr_no_commas (parser, NULL).value;
- if (t != error_mark_node)
+ {
+ c_expr texpr = c_parser_expr_no_commas (parser, NULL);
+ texpr = convert_lvalue_to_rvalue (token->location, texpr,
+ true, true);
+ t = texpr.value;
+ }
+ if (t == error_mark_node)
+ return error_mark_node;
+ mark_exp_read (t);
+ if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
{
- mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- error_at (token->location,
- "property must be integer expression");
- else
- properties = make_trait_property (NULL_TREE, t,
- properties);
+ t = c_objc_common_truthvalue_conversion (token->location,
+ t,
+ boolean_type_node);
+ if (t == error_mark_node)
+ return error_mark_node;
}
- else
- return error_mark_node;
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (token->location,
+ "property must be integer expression");
+ return error_mark_node;
+ }
+ t = c_fully_fold (t, false, NULL);
+ properties = make_trait_property (NULL_TREE, t, properties);
break;
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
@@ -26888,11 +27092,14 @@ c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
tree selectors = c_parser_omp_context_selector (parser, set, parms);
if (selectors == error_mark_node)
- ret = error_mark_node;
+ {
+ c_parser_skip_to_closing_brace (parser);
+ ret = error_mark_node;
+ }
else if (ret != error_mark_node)
ret = make_trait_set_selector (set, selectors, ret);
- braces.skip_until_found_close (parser);
+ braces.require_close (parser);
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
@@ -27797,6 +28004,151 @@ c_parser_omp_end (c_parser *parser)
}
}
+/* OpenMP 5.0
+ #pragma omp declare mapper ([mapper-identifier :] type var) \
+ [clause [ [,] clause ] ... ] new-line */
+
+static void
+c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
+{
+ tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
+ tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
+ c_token *token;
+
+ if (context == pragma_struct || context == pragma_param)
+ {
+ error ("%<#pragma omp declare mapper%> not at file or block scope");
+ goto fail;
+ }
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ goto fail;
+
+ token = c_parser_peek_token (parser);
+
+ if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ switch (token->type)
+ {
+ case CPP_NAME:
+ mapper_name = token->value;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_KEYWORD:
+ if (token->keyword == RID_DEFAULT)
+ {
+ mapper_name = NULL_TREE;
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Fallthrough. */
+ default:
+ error_at (token->location, "expected identifier or %<default%>");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ goto fail;
+ }
+
+ mapper_id = c_omp_mapper_id (mapper_name);
+ mapper_decl = c_omp_mapper_decl (mapper_id);
+
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ struct c_type_name *ctype = c_parser_type_name (parser);
+ type = groktypename (ctype, NULL, NULL);
+ if (type == error_mark_node)
+ goto fail;
+ if (!RECORD_OR_UNION_TYPE_P (type))
+ {
+ error_at (loc, "%qT is not a struct or union type in "
+ "%<#pragma omp declare mapper%>", type);
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+ for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
+ if (comptypes (TREE_PURPOSE (t), type))
+ {
+ error_at (loc, "redeclaration of %qs %<#pragma omp declare "
+ "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
+ + sizeof ("omp declare mapper ") - 1,
+ type);
+ tree prevmapper = TREE_VALUE (t);
+ /* Hmm, this location might not be very accurate. */
+ location_t ploc
+ = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
+ inform (ploc, "%<#pragma omp declare mapper%> "
+ "previously declared here");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+ }
+
+ token = c_parser_peek_token (parser);
+ if (token->type == CPP_NAME)
+ {
+ var = build_decl (token->location, VAR_DECL, token->value, type);
+ c_parser_consume_token (parser);
+ DECL_ARTIFICIAL (var) = 1;
+ }
+ else
+ {
+ error_at (token->location, "expected identifier");
+ goto fail;
+ }
+
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ goto fail;
+
+ push_scope ();
+ stmtlist = push_stmt_list ();
+ pushdecl (var);
+ DECL_CONTEXT (var) = current_function_decl;
+
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ location_t here;
+ pragma_omp_clause c_kind;
+ here = c_parser_peek_token (parser)->location;
+ c_kind = c_parser_omp_clause_name (parser);
+ if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
+ {
+ error_at (here, "unexpected clause");
+ goto fail;
+ }
+ maplist = c_parser_omp_clause_map (parser, maplist, true);
+ }
+
+ if (maplist == NULL_TREE)
+ {
+ error_at (input_location, "missing %<map%> clause");
+ goto fail;
+ }
+
+ stmt = make_node (OMP_DECLARE_MAPPER);
+ TREE_TYPE (stmt) = type;
+ OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
+ OMP_DECLARE_MAPPER_DECL (stmt) = var;
+ OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
+
+ add_stmt (stmt);
+
+ pop_stmt_list (stmtlist);
+ pop_scope ();
+
+ c_parser_skip_to_pragma_eol (parser);
+
+ t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
+ DECL_INITIAL (mapper_decl) = t;
+
+ return;
+
+ fail:
+ c_parser_skip_to_pragma_eol (parser);
+}
+
/* OpenMP 4.0
#pragma omp declare reduction (reduction-id : typename-list : expression) \
initializer-clause[opt] new-line
@@ -27923,8 +28275,8 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
location_t ploc
= DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
0));
- error_at (ploc, "previous %<#pragma omp declare "
- "reduction%>");
+ inform (ploc, "%<#pragma omp declare reduction%> "
+ "previously declared here");
break;
}
if (t == NULL_TREE)
@@ -28188,6 +28540,12 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
c_parser_omp_declare_reduction (parser, context);
return false;
}
+ if (strcmp (p, "mapper") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_declare_mapper (parser, context);
+ return false;
+ }
if (!flag_openmp) /* flag_openmp_simd */
{
c_parser_skip_to_pragma_eol (parser, false);
@@ -29097,7 +29455,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
{
error_at (match_loc, "too many %<otherwise%> or %<default%> "
"clauses in %<metadirective%>");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
default_seen = true;
@@ -29106,14 +29463,12 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
{
error_at (match_loc, "%<otherwise%> or %<default%> clause "
"must appear last in %<metadirective%>");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
if (!default_p && strcmp (p, "when") != 0)
{
error_at (match_loc, "%qs is not valid for %qs",
p, "metadirective");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
@@ -29181,7 +29536,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
if (i == 0)
{
error_at (loc, "expected directive name");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
@@ -29249,7 +29603,10 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
goto add;
case CPP_CLOSE_PAREN:
if (nesting_depth-- == 0)
- break;
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
goto add;
default:
add:
@@ -29261,8 +29618,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
break;
}
- c_parser_consume_token (parser);
-
if (!skip)
{
c_token eol_token;
@@ -29389,9 +29744,9 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
return;
error:
+ /* Skip the metadirective pragma. Do not skip the metadirective body. */
if (parser->in_pragma)
- c_parser_skip_to_pragma_eol (parser);
- c_parser_skip_to_end_of_block_or_statement (parser, true);
+ c_parser_skip_to_pragma_eol (parser, false);
}
/* Main entry point to parsing most OpenMP pragmas. */
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 2098120..364f51d 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -765,6 +765,7 @@ extern int c_type_dwarf_attribute (const_tree, int);
/* in c-typeck.cc */
extern int in_alignof;
extern int in_sizeof;
+extern int in_countof;
extern int in_typeof;
extern bool c_in_omp_for;
extern bool c_omp_array_section_p;
@@ -827,6 +828,9 @@ extern tree build_external_ref (location_t, tree, bool, tree *);
extern void pop_maybe_used (bool);
extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
extern struct c_expr c_expr_sizeof_type (location_t, struct c_type_name *);
+extern struct c_expr c_expr_countof_expr (location_t, struct c_expr);
+extern struct c_expr c_expr_countof_type (location_t loc,
+ struct c_type_name *);
extern struct c_expr parser_build_unary_op (location_t, enum tree_code,
struct c_expr);
extern struct c_expr parser_build_binary_op (location_t,
@@ -884,6 +888,10 @@ extern tree c_finish_omp_task (location_t, tree, tree);
extern void c_finish_omp_cancel (location_t, tree);
extern void c_finish_omp_cancellation_point (location_t, tree);
extern tree c_finish_omp_clauses (tree, enum c_omp_region_type);
+extern tree c_omp_finish_mapper_clauses (tree);
+extern tree c_omp_mapper_lookup (tree, tree);
+extern tree c_omp_extract_mapper_directive (tree);
+extern tree c_omp_map_array_section (location_t, tree);
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);
@@ -942,6 +950,10 @@ extern tree c_omp_reduction_id (enum tree_code, tree);
extern tree c_omp_reduction_decl (tree);
extern tree c_omp_reduction_lookup (tree, tree);
extern tree c_check_omp_declare_reduction_r (tree *, int *, void *);
+extern tree c_omp_mapper_id (tree);
+extern tree c_omp_mapper_decl (tree);
+extern void c_omp_scan_mapper_bindings (location_t, tree *, tree);
+extern tree c_omp_instantiate_mappers (tree);
extern bool c_check_in_current_scope (tree);
extern void c_pushtag (location_t, tree, tree);
extern void c_bind (location_t, tree, bool);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 0e1f842..b59b5c8a 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -72,6 +72,9 @@ int in_alignof;
/* The level of nesting inside "sizeof". */
int in_sizeof;
+/* The level of nesting inside "countof". */
+int in_countof;
+
/* The level of nesting inside "typeof". */
int in_typeof;
@@ -773,7 +776,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
construction, return it. */
for (struct composite_cache *c = cache; c != NULL; c = c->next)
- if (c->t1 == t1 && c->t2 == t2)
+ if ((c->t1 == t1 && c->t2 == t2) || (c->t1 == t2 && c->t2 == t1))
return c->composite;
/* Otherwise, create a new type node and link it into the cache. */
@@ -843,12 +846,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
n = finish_struct (input_location, n, fields, attributes, NULL,
&expr);
- n = qualify_type (n, t1);
-
- gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t1));
- gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t2));
-
- return n;
+ return qualify_type (n, t1);
}
/* FALLTHRU */
case ENUMERAL_TYPE:
@@ -1001,7 +999,15 @@ tree
composite_type (tree t1, tree t2)
{
struct composite_cache cache = { };
- return composite_type_internal (t1, t2, &cache);
+ tree n = composite_type_internal (t1, t2, &cache);
+ /* For function and arrays there are some cases where qualifiers do
+ not match. See PR120510. */
+ if (FUNCTION_TYPE != TREE_CODE (n) && ARRAY_TYPE != TREE_CODE (n))
+ {
+ gcc_checking_assert (comptypes (n, t1));
+ gcc_checking_assert (comptypes (n, t2));
+ }
+ return n;
}
/* Return the type of a conditional expression between pointers to
@@ -3540,7 +3546,7 @@ build_external_ref (location_t loc, tree id, bool fun, tree *type)
if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
{
- if (!in_sizeof && !in_typeof)
+ if (!in_sizeof && !in_typeof && !in_countof)
C_DECL_USED (ref) = 1;
else if (DECL_INITIAL (ref) == NULL_TREE
&& DECL_EXTERNAL (ref)
@@ -3596,7 +3602,7 @@ struct maybe_used_decl
{
/* The decl. */
tree decl;
- /* The level seen at (in_sizeof + in_typeof). */
+ /* The level seen at (in_sizeof + in_typeof + in_countof). */
int level;
/* The next one at this level or above, or NULL. */
struct maybe_used_decl *next;
@@ -3614,7 +3620,7 @@ record_maybe_used_decl (tree decl)
{
struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
t->decl = decl;
- t->level = in_sizeof + in_typeof;
+ t->level = in_sizeof + in_typeof + in_countof;
t->next = maybe_used_decls;
maybe_used_decls = t;
}
@@ -3628,7 +3634,7 @@ void
pop_maybe_used (bool used)
{
struct maybe_used_decl *p = maybe_used_decls;
- int cur_level = in_sizeof + in_typeof;
+ int cur_level = in_sizeof + in_typeof + in_countof;
while (p && p->level > cur_level)
{
if (used)
@@ -3738,6 +3744,110 @@ c_expr_sizeof_type (location_t loc, struct c_type_name *t)
return ret;
}
+static bool
+is_top_array_vla (tree type)
+{
+ bool zero, var;
+ tree d;
+
+ if (TREE_CODE (type) != ARRAY_TYPE)
+ return false;
+ if (!COMPLETE_TYPE_P (type))
+ return false;
+
+ d = TYPE_DOMAIN (type);
+ zero = !TYPE_MAX_VALUE (d);
+ if (zero)
+ return false;
+
+ var = (TREE_CODE (TYPE_MIN_VALUE (d)) != INTEGER_CST
+ || TREE_CODE (TYPE_MAX_VALUE (d)) != INTEGER_CST);
+ return var;
+}
+
+/* Return the result of countof applied to EXPR. */
+
+struct c_expr
+c_expr_countof_expr (location_t loc, struct c_expr expr)
+{
+ struct c_expr ret;
+ if (expr.value == error_mark_node)
+ {
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
+ ret.m_decimal = 0;
+ pop_maybe_used (false);
+ }
+ else
+ {
+ bool expr_const_operands = true;
+
+ tree folded_expr = c_fully_fold (expr.value, require_constant_value,
+ &expr_const_operands);
+ ret.value = c_countof_type (loc, TREE_TYPE (folded_expr));
+ c_last_sizeof_arg = expr.value;
+ c_last_sizeof_loc = loc;
+ ret.original_code = COUNTOF_EXPR;
+ ret.original_type = NULL;
+ ret.m_decimal = 0;
+ if (is_top_array_vla (TREE_TYPE (folded_expr)))
+ {
+ /* countof is evaluated when given a vla. */
+ ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
+ folded_expr, ret.value);
+ C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !expr_const_operands;
+ SET_EXPR_LOCATION (ret.value, loc);
+ }
+ pop_maybe_used (is_top_array_vla (TREE_TYPE (folded_expr)));
+ }
+ return ret;
+}
+
+/* Return the result of countof applied to T, a structure for the type
+ name passed to countof (rather than the type itself). LOC is the
+ location of the original expression. */
+
+struct c_expr
+c_expr_countof_type (location_t loc, struct c_type_name *t)
+{
+ tree type;
+ struct c_expr ret;
+ tree type_expr = NULL_TREE;
+ bool type_expr_const = true;
+ type = groktypename (t, &type_expr, &type_expr_const);
+ ret.value = c_countof_type (loc, type);
+ c_last_sizeof_arg = type;
+ c_last_sizeof_loc = loc;
+ ret.original_code = COUNTOF_EXPR;
+ ret.original_type = NULL;
+ ret.m_decimal = 0;
+ 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)
+ && is_top_array_vla (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
+ the result of countof does not get folded to a constant by
+ c_fully_fold, because if the number of elements is evaluated
+ the result is not constant and so
+ constraints on zero or negative size arrays must not be applied
+ when this countof call is inside another array declarator. */
+ if (!type_expr)
+ type_expr = integer_zero_node;
+ ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
+ type_expr, ret.value);
+ C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !type_expr_const;
+ }
+ pop_maybe_used (type != error_mark_node ? is_top_array_vla (type) : false);
+ return ret;
+}
+
/* Build a function call to function FUNCTION with parameters PARAMS.
The function call is at LOC.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
@@ -16840,6 +16950,12 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_MAP:
if (OMP_CLAUSE_MAP_IMPLICIT (c) && !implicit_moved)
goto move_implicit;
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ remove = true;
+ break;
+ }
/* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
@@ -17780,6 +17896,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
return clauses;
}
+/* Do processing necessary to make CLAUSES well-formed, where CLAUSES result
+ from implicit instantiation of user-defined mappers (in gimplify.cc). */
+
+tree
+c_omp_finish_mapper_clauses (tree clauses)
+{
+ return c_finish_omp_clauses (clauses, C_ORT_OMP);
+}
+
/* Return code to initialize DST with a copy constructor from SRC.
C doesn't have copy constructors nor assignment operators, only for
_Atomic vars we need to perform __atomic_load from src into a temporary