diff options
Diffstat (limited to 'gcc/c/c-decl.cc')
-rw-r--r-- | gcc/c/c-decl.cc | 316 |
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) |