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.cc524
1 files changed, 272 insertions, 252 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 8c420f2..8e8bac6 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1363,7 +1363,7 @@ pop_scope (void)
case VAR_DECL:
/* Warnings for unused variables. */
if ((!TREE_USED (p) || !DECL_READ_P (p))
- && !warning_suppressed_p (p, OPT_Wunused_but_set_variable)
+ && !warning_suppressed_p (p, OPT_Wunused_but_set_variable_)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p)
@@ -1377,7 +1377,7 @@ pop_scope (void)
}
else if (DECL_CONTEXT (p) == current_function_decl)
warning_at (DECL_SOURCE_LOCATION (p),
- OPT_Wunused_but_set_variable,
+ OPT_Wunused_but_set_variable_,
"variable %qD set but not used", p);
}
@@ -4547,21 +4547,23 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc)
= get_c_stdlib_header_for_name (IDENTIFIER_POINTER (name));
if (header_hint)
- return name_hint (NULL,
- new suggest_missing_header (loc,
- IDENTIFIER_POINTER (name),
- header_hint));
+ return name_hint
+ (nullptr,
+ std::make_unique<suggest_missing_header> (loc,
+ IDENTIFIER_POINTER (name),
+ header_hint));
/* Next, look for exact matches for builtin defines that would have been
defined if the user had passed a command-line option (e.g. -fopenmp
for "_OPENMP"). */
- diagnostic_option_id option_id
+ diagnostics::option_id option_id
= get_option_for_builtin_define (IDENTIFIER_POINTER (name));
if (option_id.m_idx > 0)
- return name_hint (nullptr,
- new suggest_missing_option (loc,
- IDENTIFIER_POINTER (name),
- option_id));
+ return name_hint
+ (nullptr,
+ std::make_unique<suggest_missing_option> (loc,
+ IDENTIFIER_POINTER (name),
+ option_id));
/* Only suggest names reserved for the implementation if NAME begins
with an underscore. */
@@ -4823,6 +4825,29 @@ c_init_decl_processing (void)
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
+
+ if (warn_keyword_macro)
+ {
+ for (unsigned int i = 0; i < num_c_common_reswords; ++i)
+ /* For C register keywords which don't start with underscore
+ or start with just single underscore. Don't complain about
+ ObjC or Transactional Memory keywords. */
+ if (c_common_reswords[i].word[0] == '_'
+ && c_common_reswords[i].word[1] == '_')
+ continue;
+ else if (c_common_reswords[i].disable
+ & (D_TRANSMEM | D_OBJC | D_CXX_OBJC))
+ continue;
+ else
+ {
+ tree id = get_identifier (c_common_reswords[i].word);
+ if (C_IS_RESERVED_WORD (id)
+ && C_RID_CODE (id) != RID_CXX_COMPAT_WARN)
+ cpp_lookup (parse_in,
+ (const unsigned char *) IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+ }
+ }
}
/* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
@@ -5721,26 +5746,6 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
}
if (TREE_CODE (decl) == FUNCTION_DECL
- && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
- {
- struct c_declarator *ce = declarator;
-
- if (ce->kind == cdk_pointer)
- ce = declarator->declarator;
- if (ce->kind == cdk_function)
- {
- tree args = ce->u.arg_info->parms;
- for (; args; args = DECL_CHAIN (args))
- {
- tree type = TREE_TYPE (args);
- if (type && INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = c_type_promotes_to (type);
- }
- }
- }
-
- if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
@@ -6226,184 +6231,7 @@ grokparm (const struct c_parm *parm, tree *expr)
return decl;
}
-/* Return attribute "arg spec" corresponding to an array/VLA parameter
- described by PARM, concatenated onto attributes ATTRS.
- The spec consists of one dollar symbol for each specified variable
- bound, one asterisk for each unspecified variable bound, followed
- by at most one specification of the most significant bound of
- an ordinary array parameter. For ordinary arrays the specification
- is either the constant bound itself, or the space character for
- an array with an unspecified bound (the [] form). Finally, a chain
- of specified variable bounds is appended to the spec, starting with
- the most significant bound. For example, the PARM T a[2][m][3][n]
- will produce __attribute__((arg spec ("[$$2]", m, n)).
- For T a typedef for an array with variable bounds, the bounds are
- included in the specification in the expected order.
- No "arg spec" is created for parameters of pointer types, making
- a distinction between T(*)[N] (or, equivalently, T[][N]) and
- the T[M][N] form, all of which have the same type and are represented
- the same, but only the last of which gets an "arg spec" describing
- the most significant bound M. */
-
-static tree
-get_parm_array_spec (const struct c_parm *parm, tree attrs)
-{
- /* The attribute specification string, minor bound first. */
- std::string spec;
-
- /* A list of VLA variable bounds, major first, or null if unspecified
- or not a VLA. */
- tree vbchain = NULL_TREE;
- /* True for a pointer parameter. */
- bool pointer = false;
- /* True for an ordinary array with an unpecified bound. */
- bool nobound = false;
-
- /* Create a string representation for the bounds of the array/VLA. */
- for (c_declarator *pd = parm->declarator, *next; pd; pd = next)
- {
- next = pd->declarator;
- while (next && next->kind == cdk_attrs)
- next = next->declarator;
-
- /* Remember if a pointer has been seen to avoid storing the constant
- bound. */
- if (pd->kind == cdk_pointer)
- pointer = true;
-
- if ((pd->kind == cdk_pointer || pd->kind == cdk_function)
- && (!next || next->kind == cdk_id))
- {
- /* Do nothing for the common case of a pointer. The fact that
- the parameter is one can be deduced from the absence of
- an arg spec for it. */
- return attrs;
- }
-
- if (pd->kind == cdk_id)
- {
- if (pointer
- || !parm->specs->type
- || TREE_CODE (parm->specs->type) != ARRAY_TYPE
- || !TYPE_DOMAIN (parm->specs->type)
- || !TYPE_MAX_VALUE (TYPE_DOMAIN (parm->specs->type)))
- continue;
-
- tree max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm->specs->type));
- if (!vbchain
- && TREE_CODE (max) == INTEGER_CST)
- {
- /* Extract the upper bound from a parameter of an array type
- unless the parameter is an ordinary array of unspecified
- bound in which case a next iteration of the loop will
- exit. */
- if (spec.empty () || spec.end ()[-1] != ' ')
- {
- if (!tree_fits_shwi_p (max))
- continue;
-
- /* The upper bound is the value of the largest valid
- index. */
- HOST_WIDE_INT n = tree_to_shwi (max) + 1;
- char buf[40];
- sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n);
- spec += buf;
- }
- continue;
- }
-
- /* For a VLA typedef, create a list of its variable bounds and
- append it in the expected order to VBCHAIN. */
- tree tpbnds = NULL_TREE;
- for (tree type = parm->specs->type; TREE_CODE (type) == ARRAY_TYPE;
- type = TREE_TYPE (type))
- {
- tree nelts_minus_one = array_type_nelts_minus_one (type);
- if (error_operand_p (nelts_minus_one))
- return attrs;
- if (TREE_CODE (nelts_minus_one) != INTEGER_CST)
- {
- /* Each variable VLA bound is represented by the dollar
- sign. */
- spec += "$";
- tpbnds = tree_cons (NULL_TREE, nelts_minus_one, tpbnds);
- }
- }
- tpbnds = nreverse (tpbnds);
- vbchain = chainon (vbchain, tpbnds);
- continue;
- }
-
- if (pd->kind != cdk_array)
- continue;
-
- if (pd->u.array.vla_unspec_p)
- {
- /* Each unspecified bound is represented by a star. There
- can be any number of these in a declaration (but none in
- a definition). */
- spec += '*';
- continue;
- }
-
- tree nelts = pd->u.array.dimen;
- if (!nelts)
- {
- /* Ordinary array of unspecified size. There can be at most
- one for the most significant bound. Exit on the next
- iteration which determines whether or not PARM is declared
- as a pointer or an array. */
- nobound = true;
- continue;
- }
-
- if (pd->u.array.static_p)
- spec += 's';
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts)))
- /* Avoid invalid NELTS. */
- return attrs;
-
- STRIP_NOPS (nelts);
- nelts = c_fully_fold (nelts, false, nullptr);
- if (TREE_CODE (nelts) == INTEGER_CST)
- {
- /* Skip all constant bounds except the most significant one.
- The interior ones are included in the array type. */
- if (next && (next->kind == cdk_array || next->kind == cdk_pointer))
- continue;
-
- if (!tree_fits_uhwi_p (nelts))
- /* Bail completely on invalid bounds. */
- return attrs;
- char buf[40];
- unsigned HOST_WIDE_INT n = tree_to_uhwi (nelts);
- sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n);
- spec += buf;
- break;
- }
-
- /* Each variable VLA bound is represented by a dollar sign. */
- spec += "$";
- vbchain = tree_cons (NULL_TREE, nelts, vbchain);
- }
-
- if (spec.empty () && !nobound)
- return attrs;
-
- spec.insert (0, "[");
- if (nobound)
- /* Ordinary array of unspecified bound is represented by a space.
- It must be last in the spec. */
- spec += ' ';
- spec += ']';
-
- tree acsstr = build_string (spec.length () + 1, spec.c_str ());
- tree args = tree_cons (NULL_TREE, acsstr, vbchain);
- tree name = get_identifier ("arg spec");
- return tree_cons (name, args, attrs);
-}
/* Given a parsed parameter declaration, decode it into a PARM_DECL
and push that on the current scope. EXPR is a pointer to an
@@ -6419,7 +6247,6 @@ push_parm_decl (const struct c_parm *parm, tree *expr)
if (decl && DECL_P (decl))
DECL_SOURCE_LOCATION (decl) = parm->loc;
- attrs = get_parm_array_spec (parm, attrs);
decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
@@ -6793,6 +6620,25 @@ add_decl_expr (location_t loc, tree type, tree *expr, bool set_name_p)
}
}
+
+/* Add attribute "arg spec" to ATTRS corresponding to an array/VLA parameter
+ declared with type TYPE. The attribute has two arguments. The first is
+ a string that encodes the presence of the static keyword. The second is
+ the declared type of the array before adjustment, i.e. as an array type
+ including the outermost bound. */
+
+static tree
+build_arg_spec_attribute (tree type, bool static_p, tree attrs)
+{
+ tree vbchain = tree_cons (NULL_TREE, type, NULL_TREE);
+ tree acsstr = static_p ? build_string (7, "static") :
+ build_string (1, "");
+ tree args = tree_cons (NULL_TREE, acsstr, vbchain);
+ tree name = get_identifier ("arg spec");
+ return tree_cons (name, args, attrs);
+}
+
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@@ -6852,6 +6698,7 @@ grokdeclarator (const struct c_declarator *declarator,
bool funcdef_flag = false;
bool funcdef_syntax = false;
bool size_varies = false;
+ bool size_error = false;
tree decl_attr = declspecs->decl_attr;
int array_ptr_quals = TYPE_UNQUALIFIED;
tree array_ptr_attrs = NULL_TREE;
@@ -7344,6 +7191,7 @@ grokdeclarator (const struct c_declarator *declarator,
"size of unnamed array has non-integer type");
size = integer_one_node;
size_int_const = true;
+ size_error = true;
}
/* This can happen with enum forward declaration. */
else if (!COMPLETE_TYPE_P (TREE_TYPE (size)))
@@ -7356,6 +7204,7 @@ grokdeclarator (const struct c_declarator *declarator,
"type");
size = integer_one_node;
size_int_const = true;
+ size_error = true;
}
size = c_fully_fold (size, false, &size_maybe_const);
@@ -7381,6 +7230,7 @@ grokdeclarator (const struct c_declarator *declarator,
error_at (loc, "size of unnamed array is negative");
size = integer_one_node;
size_int_const = true;
+ size_error = true;
}
/* Handle a size folded to an integer constant but
not an integer constant expression. */
@@ -7996,6 +7846,10 @@ grokdeclarator (const struct c_declarator *declarator,
if (TREE_CODE (type) == ARRAY_TYPE)
{
+ if (!size_error)
+ *decl_attrs = build_arg_spec_attribute (type, array_parm_static,
+ *decl_attrs);
+
/* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type);
if (orig_qual_type != NULL_TREE)
@@ -8961,12 +8815,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);
@@ -9665,15 +9521,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
@@ -9803,12 +9662,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;
@@ -9909,6 +9773,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.
@@ -9941,7 +9806,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);
}
@@ -10115,12 +9980,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",
@@ -10279,7 +10146,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;
@@ -10303,6 +10173,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. */
@@ -10314,7 +10185,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 */
@@ -11179,13 +11050,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
useful for argument types like uid_t. */
DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
- if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl))
- && INTEGRAL_TYPE_P (TREE_TYPE (parm))
- && (TYPE_PRECISION (TREE_TYPE (parm))
- < TYPE_PRECISION (integer_type_node)))
- DECL_ARG_TYPE (parm)
- = c_type_promotes_to (TREE_TYPE (parm));
-
/* ??? Is it possible to get here with a
built-in prototype or will it always have
been diagnosed as conflicting with an
@@ -11413,19 +11277,6 @@ finish_function (location_t end_loc)
if (c_dialect_objc ())
objc_finish_function ();
- if (TREE_CODE (fndecl) == FUNCTION_DECL
- && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
- {
- tree args = DECL_ARGUMENTS (fndecl);
- for (; args; args = DECL_CHAIN (args))
- {
- tree type = TREE_TYPE (args);
- if (INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = c_type_promotes_to (type);
- }
- }
-
if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
@@ -11486,9 +11337,9 @@ finish_function (location_t end_loc)
&& !DECL_READ_P (decl)
&& DECL_NAME (decl)
&& !DECL_ARTIFICIAL (decl)
- && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter))
+ && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter_))
warning_at (DECL_SOURCE_LOCATION (decl),
- OPT_Wunused_but_set_parameter,
+ OPT_Wunused_but_set_parameter_,
"parameter %qD set but not used", decl);
}
@@ -13857,6 +13708,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)
@@ -13899,7 +13918,8 @@ c_get_loop_names (tree before_labels, bool switch_p, tree *last_p)
++ret;
}
}
- else if (TREE_CODE (stmt) != CASE_LABEL_EXPR)
+ else if (TREE_CODE (stmt) != CASE_LABEL_EXPR
+ && TREE_CODE (stmt) != DEBUG_BEGIN_STMT)
break;
}
if (last)