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.cc316
1 files changed, 257 insertions, 59 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index ad66d7d..7e1c197 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);
@@ -9430,56 +9432,62 @@ c_update_type_canonical (tree t)
}
}
-/* Verify the argument of the counted_by attribute of the flexible array
- member FIELD_DECL is a valid field of the containing structure,
- STRUCT_TYPE, Report error and remove this attribute when it's not. */
+/* Verify the argument of the counted_by attribute of each of the
+ FIELDS_WITH_COUNTED_BY is a valid field of the containing structure,
+ STRUCT_TYPE, Report error and remove the corresponding attribute
+ when it's not. */
static void
-verify_counted_by_attribute (tree struct_type, tree field_decl)
+verify_counted_by_attribute (tree struct_type,
+ auto_vec<tree> *fields_with_counted_by)
{
- tree attr_counted_by = lookup_attribute ("counted_by",
- DECL_ATTRIBUTES (field_decl));
+ for (tree field_decl : *fields_with_counted_by)
+ {
+ tree attr_counted_by = lookup_attribute ("counted_by",
+ DECL_ATTRIBUTES (field_decl));
- if (!attr_counted_by)
- return;
+ if (!attr_counted_by)
+ continue;
- /* If there is an counted_by attribute attached to the field,
- verify it. */
+ /* If there is an counted_by attribute attached to the field,
+ verify it. */
- tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by));
+ tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by));
- /* Verify the argument of the attrbute is a valid field of the
- containing structure. */
+ /* Verify the argument of the attrbute is a valid field of the
+ containing structure. */
- tree counted_by_field = lookup_field (struct_type, fieldname);
+ tree counted_by_field = lookup_field (struct_type, fieldname);
- /* Error when the field is not found in the containing structure and
- remove the corresponding counted_by attribute from the field_decl. */
- if (!counted_by_field)
- {
- error_at (DECL_SOURCE_LOCATION (field_decl),
- "argument %qE to the %<counted_by%> attribute"
- " is not a field declaration in the same structure"
- " as %qD", fieldname, field_decl);
- DECL_ATTRIBUTES (field_decl)
- = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl));
- }
- else
- /* Error when the field is not with an integer type. */
- {
- while (TREE_CHAIN (counted_by_field))
- counted_by_field = TREE_CHAIN (counted_by_field);
- tree real_field = TREE_VALUE (counted_by_field);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field)))
+ /* Error when the field is not found in the containing structure and
+ remove the corresponding counted_by attribute from the field_decl. */
+ if (!counted_by_field)
{
error_at (DECL_SOURCE_LOCATION (field_decl),
"argument %qE to the %<counted_by%> attribute"
- " is not a field declaration with an integer type",
- fieldname);
+ " is not a field declaration in the same structure"
+ " as %qD", fieldname, field_decl);
DECL_ATTRIBUTES (field_decl)
= remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl));
}
+ else
+ /* Error when the field is not with an integer type. */
+ {
+ while (TREE_CHAIN (counted_by_field))
+ counted_by_field = TREE_CHAIN (counted_by_field);
+ tree real_field = TREE_VALUE (counted_by_field);
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field)))
+ {
+ error_at (DECL_SOURCE_LOCATION (field_decl),
+ "argument %qE to the %<counted_by%> attribute"
+ " is not a field declaration with an integer type",
+ fieldname);
+ DECL_ATTRIBUTES (field_decl)
+ = remove_attribute ("counted_by",
+ DECL_ATTRIBUTES (field_decl));
+ }
+ }
}
}
@@ -9554,7 +9562,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
until now.) */
bool saw_named_field = false;
- tree counted_by_fam_field = NULL_TREE;
+ auto_vec<tree> fields_with_counted_by;
for (x = fieldlist; x; x = DECL_CHAIN (x))
{
/* Whether this field is the last field of the structure or union.
@@ -9635,9 +9643,16 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
record it here and do more verification later after the
whole structure is complete. */
if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x)))
- counted_by_fam_field = x;
+ fields_with_counted_by.safe_push (x);
}
+ if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE)
+ /* If there is a counted_by attribute attached to this field,
+ record it here and do more verification later after the
+ whole structure is complete. */
+ if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x)))
+ fields_with_counted_by.safe_push (x);
+
if (pedantic && TREE_CODE (t) == RECORD_TYPE
&& flexible_array_type_p (TREE_TYPE (x)))
pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
@@ -9647,15 +9662,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 +9803,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 +9914,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,12 +9947,12 @@ 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);
}
- if (counted_by_fam_field)
- verify_counted_by_attribute (t, counted_by_fam_field);
+ if (fields_with_counted_by.length () > 0)
+ verify_counted_by_attribute (t, &fields_with_counted_by);
return t;
}
@@ -10097,12 +10121,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 +10287,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 +10314,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 +10326,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 +13849,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)