aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-decl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c/c-decl.cc')
-rw-r--r--gcc/c/c-decl.cc225
1 files changed, 205 insertions, 20 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index ad66d7d..8bbd6eb 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
@@ -9785,12 +9790,17 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
len += list_length (x);
/* Use the same allocation policy here that make_node uses, to
- ensure that this lives as long as the rest of the struct decl.
- All decls in an inline function need to be saved. */
-
- space = ggc_cleared_alloc<struct lang_type> ();
- space2 = (sorted_fields_type *) ggc_internal_alloc
- (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+ ensure that this lives as long as the rest of the struct decl.
+ All decls in an inline function need to be saved. */
+
+ space = ((struct lang_type *)
+ ggc_internal_cleared_alloc (c_dialect_objc ()
+ ? sizeof (struct lang_type)
+ : offsetof (struct lang_type,
+ info)));
+ space2 = ((sorted_fields_type *)
+ ggc_internal_alloc (sizeof (struct sorted_fields_type)
+ + len * sizeof (tree)));
len = 0;
space->s = space2;
@@ -9891,6 +9901,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 +9934,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 +10108,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",
@@ -10261,7 +10274,10 @@ finish_enum (tree enumtype, tree values, tree attributes)
/* Record the min/max values so that we can warn about bit-field
enumerations that are too small for the values. */
- lt = ggc_cleared_alloc<struct lang_type> ();
+ lt = ((struct lang_type *)
+ ggc_internal_cleared_alloc (c_dialect_objc ()
+ ? sizeof (struct lang_type)
+ : offsetof (struct lang_type, info)));
lt->enum_min = minnode;
lt->enum_max = maxnode;
TYPE_LANG_SPECIFIC (enumtype) = lt;
@@ -10285,6 +10301,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 +10313,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 +13836,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)