aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-10-12 09:46:38 -0700
committerIan Lance Taylor <iant@golang.org>2020-10-12 09:46:38 -0700
commit9cd320ea6572c577cdf17ce1f9ea5230b166af6d (patch)
treed1c8e7c2e09a91ed75f0e5476c648c2e745aa2de /gcc/c
parent4854d721be78358e59367982bdd94461b4be3c5a (diff)
parent3175d40fc52fb8eb3c3b18cc343d773da24434fb (diff)
downloadgcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.zip
gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.tar.gz
gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.tar.bz2
Merge from trunk revision 3175d40fc52fb8eb3c3b18cc343d773da24434fb.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog114
-rw-r--r--gcc/c/c-decl.c253
-rw-r--r--gcc/c/c-lang.h3
-rw-r--r--gcc/c/c-objc-common.h4
-rw-r--r--gcc/c/c-parser.c197
-rw-r--r--gcc/c/c-tree.h23
-rw-r--r--gcc/c/c-typeck.c295
-rw-r--r--gcc/c/gimple-parser.c4
8 files changed, 588 insertions, 305 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8e179a3..839bfa1 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,115 @@
+2020-09-19 Martin Sebor <msebor@redhat.com>
+
+ PR c/50584
+ * c-decl.c (lookup_last_decl): Define new function.
+ (c_decl_attributes): Call it.
+ (start_decl): Add argument and use it.
+ (finish_decl): Call build_attr_access_from_parms and decl_attributes.
+ (get_parm_array_spec): Define new function.
+ (push_parm_decl): Call get_parm_array_spec.
+ (start_function): Call warn_parm_array_mismatch. Build attribute
+ access and add it to current function.
+ * c-parser.c (c_parser_declaration_or_fndef): Diagnose mismatches
+ in forms of array parameters.
+ * c-tree.h (start_decl): Add argument.
+
+2020-09-19 Sandra Loosemore <sandra@codesourcery.com>
+
+ * c-decl.c (c_break_label, c_cont_label): Delete, and replace
+ with...
+ (in_statement): New.
+ (start_function): Adjust for above change.
+ (c_push_function_context, c_pop_function_context): Likewise.
+ * c-lang.h (struct language_function): Likewise.
+ * c-objc-common.h (LANG_HOOKS_BLOCK_MAY_FALLTHRU): Define.
+ * c-parser.c (objc_foreach_break_label, objc_foreach_continue_label):
+ New.
+ (c_parser_statement_after_labels): Adjust calls to c_finish_bc_stmt.
+ (c_parser_switch_statement): Adjust break/switch context handling
+ and calls to renamed functions.
+ (c_parser_while_statement): Adjust break/switch context handling and
+ build a WHILE_STMT.
+ (c_parser_do_statement): Ditto, with DO_STMT respectively.
+ (c_parser_for_statement): Ditto, with FOR_STMT respectively.
+ (c_parser_omp_for_loop): Adjust break/switch context handling.
+ * c-tree.h (c_break_label, c_cont_label): Delete.
+ (IN_SWITCH_STMT, IN_ITERATION_STMT): Define.
+ (IN_OMP_BLOCK, IN_OMP_FOR, IN_OBJC_FOREACH): Define.
+ (in_statement, switch_statement_break_seen_p): Declare.
+ (c_start_case, c_finish_case): Renamed to...
+ (c_start_switch, c_finish_switch).
+ (c_finish_bc_stmt): Adjust arguments.
+ * c-typeck.c (build_function_call_vec): Don't try to print
+ statements with %qE format.
+ (struct c_switch): Rename switch_expr field to switch_stmt.
+ Add break_stmt_seen_p field.
+ (c_start_case): Rename to c_start_switch. Build a SWITCH_STMT
+ instead of a SWITCH_EXPR. Update for changes to struct c_switch.
+ (do_case): Update for changes to struct c_switch.
+ (c_finish_case): Rename to c_finish_switch. Update for changes to
+ struct c_switch and change of representation from SWITCH_EXPR to
+ SWITCH_STMT.
+ (c_finish_loop): Delete.
+ (c_finish_bc_stmt): Update to reflect changes to break/continue
+ state representation. Build a BREAK_STMT or CONTINUE_STMT instead
+ of a GOTO_EXPR except for objc foreach loops.
+
+2020-09-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/96867
+ * c-typeck.c (handle_omp_array_sections_1): Test C_ARRAY_PARAMETER
+ only on PARM_DECLs.
+
+2020-08-28 Martin Sebor <msebor@redhat.com>
+
+ PR c/96596
+ * c-decl.c (match_builtin_function_types): Avoid dealing with erroneous
+ argument type.
+
+2020-08-27 Martin Liska <mliska@suse.cz>
+
+ * gimple-parser.c (c_parser_gimple_compound_statement): Set exact argument of a vector
+ growth function to true.
+
+2020-08-25 Tobias Burnus <tobias@codesourcery.com>
+
+ PR c/96678
+ * c-typeck.c (handle_omp_array_sections_1): Talk about
+ array function parameter in the error message.
+
+2020-08-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/96571
+ * c-parser.c (c_parser_generic_selection): Change match_found from bool
+ to int, holding index of the match. Call mark_exp_read on the selector
+ expression and on expressions other than the selected one.
+
+2020-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR c/96377
+ * c-typeck.c (process_init_element): Split test for whether to
+ recurse into a record, union or array into...
+ (initialize_elementwise_p): ...this new function. Don't recurse
+ into a vector type if the initialization value is also a vector.
+
+2020-07-31 Richard Biener <rguenther@suse.de>
+
+ PR debug/96383
+ * c-objc-common.h (LANG_HOOKS_FINALIZE_EARLY_DEBUG):
+ Define to c_common_finalize_early_debug.
+
+2020-07-22 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_hint): Require nonnegative hint clause.
+ (c_parser_omp_critical): Permit hint(0) clause without named critical.
+ (c_parser_omp_construct): Don't assert if error_mark_node is returned.
+
+2020-07-21 Sunil K Pandey <skpgkp2@gmail.com>
+
+ PR target/95237
+ * c-decl.c (finish_decl): Call target hook
+ lower_local_decl_alignment to lower local decl alignment.
+
2020-07-09 Julian Brown <julian@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com>
@@ -5,7 +117,7 @@
* c-typeck.c (c_finish_omp_clauses): Set OMP_CLAUSE_SIZE (bias) to zero
for standalone attach/detach clauses.
-2020-07-08 Eric Botcazou <ebotcazou@gcc.gnu.org>
+2020-07-08 Eric Botcazou <ebotcazou@adacore.com>
* c-typeck.c (convert_for_assignment): If -Wscalar-storage-order is
set, warn for conversion between pointers that point to incompatible
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 81bd2ee..81b9adb 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
line numbers. For example, the CONST_DECLs for enum values. */
#include "config.h"
+#define INCLUDE_STRING
#define INCLUDE_UNIQUE_PTR
#include "system.h"
#include "coretypes.h"
@@ -58,6 +59,8 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/known-headers.h"
#include "c-family/c-spellcheck.h"
+#include "tree-pretty-print.h"
+
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
{ NORMAL, /* Ordinary declaration */
@@ -112,9 +115,9 @@ struct obstack parser_obstack;
static GTY(()) struct stmt_tree_s c_stmt_tree;
-/* State saving variables. */
-tree c_break_label;
-tree c_cont_label;
+/* Zero if we are not in an iteration or switch statement, otherwise
+ a bitmask. See bitmask definitions in c-tree.h. */
+unsigned char in_statement;
/* A list of decls to be made automatically visible in each file scope. */
static GTY(()) tree visible_builtins;
@@ -1712,7 +1715,10 @@ match_builtin_function_types (tree newtype, tree oldtype,
return NULL_TREE;
tree oldtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs));
- tree newtype = TYPE_MAIN_VARIANT (TREE_VALUE (newargs));
+ tree newtype = TREE_VALUE (newargs);
+ if (newtype == error_mark_node)
+ return NULL_TREE;
+ newtype = TYPE_MAIN_VARIANT (newtype);
if (!types_close_enough_to_match (oldtype, newtype))
return NULL_TREE;
@@ -4967,6 +4973,17 @@ groktypename (struct c_type_name *type_name, tree *expr,
return type;
}
+/* Looks up the most recent pushed declaration corresponding to DECL. */
+
+static tree
+lookup_last_decl (tree decl)
+{
+ tree last_decl = lookup_name (DECL_NAME (decl));
+ if (!last_decl)
+ last_decl = lookup_name_in_scope (DECL_NAME (decl), external_scope);
+ return last_decl;
+}
+
/* Wrapper for decl_attributes that adds some implicit attributes
to VAR_DECLs or FUNCTION_DECLs. */
@@ -4995,10 +5012,7 @@ c_decl_attributes (tree *node, tree attributes, int flags)
so far so that attributes on the current declaration that's
about to be pushed that conflict with the former can be detected,
diagnosed, and rejected as appropriate. */
- tree last_decl = lookup_name (DECL_NAME (*node));
- if (!last_decl)
- last_decl = lookup_name_in_scope (DECL_NAME (*node), external_scope);
-
+ tree last_decl = lookup_last_decl (*node);
return decl_attributes (node, attributes, flags, last_decl);
}
@@ -5008,6 +5022,8 @@ c_decl_attributes (tree *node, tree attributes, int flags)
have been parsed, before parsing the initializer if any.
Here we create the ..._DECL node, fill in its type,
and put it on the list of decls for the current context.
+ When nonnull, set *LASTLOC to the location of the prior declaration
+ of the same entity if one exists.
The ..._DECL node is returned as the value.
Exception: for arrays where the length is not specified,
@@ -5020,7 +5036,7 @@ c_decl_attributes (tree *node, tree attributes, int flags)
tree
start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
- bool initialized, tree attributes)
+ bool initialized, tree attributes, location_t *lastloc /* = NULL */)
{
tree decl;
tree tem;
@@ -5038,6 +5054,10 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
if (!decl || decl == error_mark_node)
return NULL_TREE;
+ if (tree lastdecl = lastloc ? lookup_last_decl (decl) : NULL_TREE)
+ if (lastdecl != error_mark_node)
+ *lastloc = DECL_SOURCE_LOCATION (lastdecl);
+
if (expr)
add_stmt (fold_convert (void_type_node, expr));
@@ -5475,6 +5495,14 @@ finish_decl (tree decl, location_t init_loc, tree init,
if (asmspec && VAR_P (decl) && C_DECL_REGISTER (decl))
DECL_HARD_REGISTER (decl) = 1;
rest_of_decl_compilation (decl, true, 0);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ tree parms = DECL_ARGUMENTS (decl);
+ const bool builtin = fndecl_built_in_p (decl);
+ if (tree access = build_attr_access_from_parms (parms, !builtin))
+ decl_attributes (&decl, access, 0);
+ }
}
else
{
@@ -5600,6 +5628,13 @@ finish_decl (tree decl, location_t init_loc, tree init,
NULL_TREE, DECL_ATTRIBUTES (decl));
}
+ /* This is the last point we can lower alignment so give the target the
+ chance to do so. */
+ if (VAR_P (decl)
+ && !is_global_var (decl)
+ && !DECL_HARD_REGISTER (decl))
+ targetm.lower_local_decl_alignment (decl);
+
invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
}
@@ -5620,6 +5655,175 @@ 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, "%lu", (unsigned long)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 = array_type_nelts (type);
+ if (TREE_CODE (nelts) != INTEGER_CST)
+ {
+ /* Each variable VLA bound is represented by the dollar
+ sign. */
+ spec += "$";
+ tpbnds = tree_cons (NULL_TREE, nelts, 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 (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];
+ const char *code = pd->u.array.static_p ? "s" : "";
+ unsigned HOST_WIDE_INT n = tree_to_uhwi (nelts);
+ sprintf (buf, "%s%llu", code, (unsigned long long)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
expression that needs to be evaluated for the side effects of array
@@ -5629,12 +5833,12 @@ void
push_parm_decl (const struct c_parm *parm, tree *expr)
{
tree attrs = parm->attrs;
- tree decl;
-
- decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
- &attrs, expr, NULL, DEPRECATED_NORMAL);
+ tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
+ &attrs, expr, NULL, DEPRECATED_NORMAL);
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);
@@ -9153,10 +9357,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
warn_about_return_type = 0;
c_switch_stack = NULL;
- /* Indicate no valid break/continue context by setting these variables
- to some non-null, non-label value. We'll notice and emit the proper
- error message in c_finish_bc_stmt. */
- c_break_label = c_cont_label = size_zero_node;
+ /* Indicate no valid break/continue context. */
+ in_statement = 0;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
&attributes, NULL, NULL, DEPRECATED_NORMAL);
@@ -9220,6 +9422,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL)
old_decl = NULL_TREE;
+
current_function_prototype_locus = UNKNOWN_LOCATION;
current_function_prototype_built_in = false;
current_function_prototype_arg_types = NULL_TREE;
@@ -9350,12 +9553,22 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
"%qD is normally a non-static function", decl1);
}
+ tree parms = current_function_arg_info->parms;
+ if (old_decl)
+ {
+ location_t origloc = DECL_SOURCE_LOCATION (old_decl);
+ warn_parm_array_mismatch (origloc, old_decl, parms);
+ }
+
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
current_function_decl = pushdecl (decl1);
+ if (tree access = build_attr_access_from_parms (parms, false))
+ decl_attributes (&current_function_decl, access, 0, old_decl);
+
push_scope ();
declare_parm_level ();
@@ -10157,8 +10370,7 @@ c_push_function_context (void)
p->base.x_stmt_tree = c_stmt_tree;
c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
- p->x_break_label = c_break_label;
- p->x_cont_label = c_cont_label;
+ p->x_in_statement = in_statement;
p->x_switch_stack = c_switch_stack;
p->arg_info = current_function_arg_info;
p->returns_value = current_function_returns_value;
@@ -10197,8 +10409,7 @@ c_pop_function_context (void)
c_stmt_tree = p->base.x_stmt_tree;
p->base.x_stmt_tree.x_cur_stmt_list = NULL;
- c_break_label = p->x_break_label;
- c_cont_label = p->x_cont_label;
+ in_statement = p->x_in_statement;
c_switch_stack = p->x_switch_stack;
current_function_arg_info = p->arg_info;
current_function_returns_value = p->returns_value;
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 6d377cd..7e9a276 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -51,8 +51,7 @@ struct GTY(()) lang_decl {
struct GTY(()) language_function {
struct c_language_function base;
- tree x_break_label;
- tree x_cont_label;
+ unsigned char x_in_statement;
struct c_switch * GTY((skip)) x_switch_stack;
struct c_arg_info * GTY((skip)) arg_info;
int returns_value;
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index 5471fc7..76f9db7 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see
#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
#undef LANG_HOOKS_MISSING_NORETURN_OK_P
#define LANG_HOOKS_MISSING_NORETURN_OK_P c_missing_noreturn_ok_p
+#undef LANG_HOOKS_BLOCK_MAY_FALLTHRU
+#define LANG_HOOKS_BLOCK_MAY_FALLTHRU c_block_may_fallthru
#undef LANG_HOOKS_BUILTIN_FUNCTION
#define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function
#undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
@@ -65,6 +67,8 @@ along with GCC; see the file COPYING3. If not see
c_simulate_builtin_function_decl
#undef LANG_HOOKS_EMITS_BEGIN_STMT
#define LANG_HOOKS_EMITS_BEGIN_STMT true
+#undef LANG_HOOKS_FINALIZE_EARLY_DEBUG
+#define LANG_HOOKS_FINALIZE_EARLY_DEBUG c_common_finalize_early_debug
/* Attribute hooks. */
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 275b8a3..7d58356 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "c-family/name-hint.h"
#include "tree-iterator.h"
+#include "tree-pretty-print.h"
#include "memmodel.h"
#include "c-family/known-headers.h"
@@ -1479,6 +1480,9 @@ struct oacc_routine_data {
location_t loc;
};
+/* Used for parsing objc foreach statements. */
+static tree objc_foreach_break_label, objc_foreach_continue_label;
+
static bool c_parser_nth_token_starts_std_attributes (c_parser *,
unsigned int);
static tree c_parser_std_attribute_specifier_sequence (c_parser *);
@@ -2296,13 +2300,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
- tree d = start_decl (declarator, specs, false,
- chainon (postfix_attrs,
- all_prefix_attrs));
- if (d
- && TREE_CODE (d) == FUNCTION_DECL
- && DECL_ARGUMENTS (d) == NULL_TREE
- && DECL_INITIAL (d) == NULL_TREE)
+
+ location_t lastloc = UNKNOWN_LOCATION;
+ tree attrs = chainon (postfix_attrs, all_prefix_attrs);
+ tree d = start_decl (declarator, specs, false, attrs, &lastloc);
+ if (d && TREE_CODE (d) == FUNCTION_DECL)
{
/* Find the innermost declarator that is neither cdk_id
nor cdk_attrs. */
@@ -2331,10 +2333,18 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
gcc_unreachable ();
}
- /* If it exists and is cdk_function, use its parameters. */
+ /* If it exists and is cdk_function declaration whose
+ arguments have not been set yet, use its arguments. */
if (last_non_id_attrs
&& last_non_id_attrs->kind == cdk_function)
- DECL_ARGUMENTS (d) = last_non_id_attrs->u.arg_info->parms;
+ {
+ tree parms = last_non_id_attrs->u.arg_info->parms;
+ if (DECL_ARGUMENTS (d) == NULL_TREE
+ && DECL_INITIAL (d) == NULL_TREE)
+ DECL_ARGUMENTS (d) = parms;
+
+ warn_parm_array_mismatch (lastloc, d, parms);
+ }
}
if (omp_declare_simd_clauses.exists ())
{
@@ -2363,7 +2373,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name);
-
+
if (c_parser_next_token_is_keyword (parser, RID_IN))
{
if (d)
@@ -6221,11 +6231,11 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
goto expect_semicolon;
case RID_CONTINUE:
c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
+ stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false);
goto expect_semicolon;
case RID_BREAK:
c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (loc, &c_break_label, true);
+ stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true);
goto expect_semicolon;
case RID_RETURN:
c_parser_consume_token (parser);
@@ -6627,7 +6637,8 @@ static void
c_parser_switch_statement (c_parser *parser, bool *if_p)
{
struct c_expr ce;
- tree block, expr, body, save_break;
+ tree block, expr, body;
+ unsigned char save_in_statement;
location_t switch_loc = c_parser_peek_token (parser)->location;
location_t switch_cond_loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
@@ -6653,9 +6664,9 @@ c_parser_switch_statement (c_parser *parser, bool *if_p)
expr = error_mark_node;
ce.original_type = error_mark_node;
}
- c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
- save_break = c_break_label;
- c_break_label = NULL_TREE;
+ c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p);
+ save_in_statement = in_statement;
+ in_statement |= IN_SWITCH_STMT;
location_t loc_after_labels;
bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
@@ -6663,16 +6674,8 @@ c_parser_switch_statement (c_parser *parser, bool *if_p)
if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
RID_SWITCH);
- if (c_break_label)
- {
- location_t here = c_parser_peek_token (parser)->location;
- tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
- SET_EXPR_LOCATION (t, here);
- SWITCH_BREAK_LABEL_P (c_break_label) = 1;
- append_to_statement_list_force (t, &body);
- }
- c_finish_case (body, ce.original_type);
- c_break_label = save_break;
+ c_finish_switch (body, ce.original_type);
+ in_statement = save_in_statement;
add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
c_parser_maybe_reclassify_token (parser);
}
@@ -6690,7 +6693,8 @@ static void
c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
bool *if_p)
{
- tree block, cond, body, save_break, save_cont;
+ tree block, cond, body;
+ unsigned char save_in_statement;
location_t loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
token_indent_info while_tinfo
@@ -6709,10 +6713,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
build_int_cst (integer_type_node,
annot_expr_unroll_kind),
build_int_cst (integer_type_node, unroll));
- save_break = c_break_label;
- c_break_label = NULL_TREE;
- save_cont = c_cont_label;
- c_cont_label = NULL_TREE;
+ save_in_statement = in_statement;
+ in_statement = IN_ITERATION_STMT;
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -6720,8 +6722,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
location_t loc_after_labels;
bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
- c_finish_loop (loc, loc, cond, UNKNOWN_LOCATION, NULL, body,
- c_break_label, c_cont_label, true);
+ add_stmt (build_stmt (loc, WHILE_STMT, cond, body));
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_parser_maybe_reclassify_token (parser);
@@ -6733,8 +6734,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
while_tinfo.location, RID_WHILE);
- c_break_label = save_break;
- c_cont_label = save_cont;
+ in_statement = save_in_statement;
}
/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
@@ -6746,7 +6746,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
static void
c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
{
- tree block, cond, body, save_break, save_cont, new_break, new_cont;
+ tree block, cond, body;
+ unsigned char save_in_statement;
location_t loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
c_parser_consume_token (parser);
@@ -6756,17 +6757,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
"suggest braces around empty body in %<do%> statement");
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
- save_break = c_break_label;
- c_break_label = NULL_TREE;
- save_cont = c_cont_label;
- c_cont_label = NULL_TREE;
+ save_in_statement = in_statement;
+ in_statement = IN_ITERATION_STMT;
body = c_parser_c99_block_statement (parser, NULL);
c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
- new_break = c_break_label;
- c_break_label = save_break;
- new_cont = c_cont_label;
- c_cont_label = save_cont;
- location_t cond_loc = c_parser_peek_token (parser)->location;
+ in_statement = save_in_statement;
cond = c_parser_paren_condition (parser);
if (ivdep && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
@@ -6780,8 +6775,8 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
build_int_cst (integer_type_node, unroll));
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
- c_finish_loop (loc, cond_loc, cond, UNKNOWN_LOCATION, NULL, body,
- new_break, new_cont, false);
+
+ add_stmt (build_stmt (loc, DO_STMT, cond, body));
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
@@ -6848,15 +6843,15 @@ static void
c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
bool *if_p)
{
- tree block, cond, incr, save_break, save_cont, body;
+ tree block, cond, incr, body;
+ unsigned char save_in_statement;
+ tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
/* The following are only used when parsing an ObjC foreach statement. */
tree object_expression;
/* Silence the bogus uninitialized warning. */
tree collection_expression = NULL;
location_t loc = c_parser_peek_token (parser)->location;
location_t for_loc = loc;
- location_t cond_loc = UNKNOWN_LOCATION;
- location_t incr_loc = UNKNOWN_LOCATION;
bool is_foreach_statement = false;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
token_indent_info for_tinfo
@@ -6966,7 +6961,6 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
gcc_assert (!parser->objc_could_be_foreach_context);
if (!is_foreach_statement)
{
- cond_loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
if (ivdep)
@@ -7007,7 +7001,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
/* Parse the increment expression (the third expression in a
for-statement). In the case of a foreach-statement, this is
the expression that follows the 'in'. */
- loc = incr_loc = c_parser_peek_token (parser)->location;
+ loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
if (is_foreach_statement)
@@ -7033,10 +7027,17 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
}
parens.skip_until_found_close (parser);
}
- save_break = c_break_label;
- c_break_label = NULL_TREE;
- save_cont = c_cont_label;
- c_cont_label = NULL_TREE;
+ save_in_statement = in_statement;
+ if (is_foreach_statement)
+ {
+ in_statement = IN_OBJC_FOREACH;
+ save_objc_foreach_break_label = objc_foreach_break_label;
+ save_objc_foreach_continue_label = objc_foreach_continue_label;
+ objc_foreach_break_label = create_artificial_label (loc);
+ objc_foreach_continue_label = create_artificial_label (loc);
+ }
+ else
+ in_statement = IN_ITERATION_STMT;
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -7047,11 +7048,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
if (is_foreach_statement)
objc_finish_foreach_loop (for_loc, object_expression,
- collection_expression, body, c_break_label,
- c_cont_label);
+ collection_expression, body,
+ objc_foreach_break_label,
+ objc_foreach_continue_label);
else
- c_finish_loop (for_loc, cond_loc, cond, incr_loc, incr, body,
- c_break_label, c_cont_label, true);
+ add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
+ body, NULL_TREE));
add_stmt (c_end_compound_stmt (for_loc, block,
flag_isoc99 || c_dialect_objc ()));
c_parser_maybe_reclassify_token (parser);
@@ -7064,8 +7066,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
for_tinfo.location, RID_FOR);
- c_break_label = save_break;
- c_cont_label = save_cont;
+ in_statement = save_in_statement;
+ if (is_foreach_statement)
+ {
+ objc_foreach_break_label = save_objc_foreach_break_label;
+ objc_foreach_continue_label = save_objc_foreach_continue_label;
+ }
}
/* Parse an asm statement, a GNU extension. This is a full-blown asm
@@ -8686,7 +8692,7 @@ c_parser_generic_selection (c_parser *parser)
struct c_expr selector, error_expr;
tree selector_type;
struct c_generic_association matched_assoc;
- bool match_found = false;
+ int match_found = -1;
location_t generic_loc, selector_loc;
error_expr.original_code = ERROR_MARK;
@@ -8721,6 +8727,7 @@ c_parser_generic_selection (c_parser *parser)
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return selector;
}
+ mark_exp_read (selector.value);
selector_type = TREE_TYPE (selector.value);
/* In ISO C terms, rvalues (including the controlling expression of
_Generic) do not have qualified types. */
@@ -8820,18 +8827,18 @@ c_parser_generic_selection (c_parser *parser)
if (assoc.type == NULL_TREE)
{
- if (!match_found)
+ if (match_found < 0)
{
matched_assoc = assoc;
- match_found = true;
+ match_found = associations.length ();
}
}
else if (comptypes (assoc.type, selector_type))
{
- if (!match_found || matched_assoc.type == NULL_TREE)
+ if (match_found < 0 || matched_assoc.type == NULL_TREE)
{
matched_assoc = assoc;
- match_found = true;
+ match_found = associations.length ();
}
else
{
@@ -8849,13 +8856,19 @@ c_parser_generic_selection (c_parser *parser)
c_parser_consume_token (parser);
}
+ unsigned int ix;
+ struct c_generic_association *iter;
+ FOR_EACH_VEC_ELT (associations, ix, iter)
+ if (ix != (unsigned) match_found)
+ mark_exp_read (iter->expression.value);
+
if (!parens.require_close (parser))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return error_expr;
}
- if (!match_found)
+ if (match_found < 0)
{
error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
"compatible with any association",
@@ -13901,16 +13914,15 @@ c_parser_omp_clause_hint (c_parser *parser, tree list)
expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- || TREE_CODE (t) != INTEGER_CST)
+ || TREE_CODE (t) != INTEGER_CST
+ || tree_int_cst_sgn (t) == -1)
{
- c_parser_error (parser, "expected constant integer expression");
+ c_parser_error (parser, "expected constant integer expression "
+ "with valid sync-hint value");
return list;
}
-
+ parens.skip_until_found_close (parser);
check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint");
c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
@@ -17795,18 +17807,9 @@ c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
if (c_parser_next_token_is (parser, CPP_COMMA)
&& c_parser_peek_2nd_token (parser)->type == CPP_NAME)
c_parser_consume_token (parser);
-
- clauses = c_parser_omp_all_clauses (parser,
- OMP_CRITICAL_CLAUSE_MASK,
- "#pragma omp critical");
}
- else
- {
- if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- c_parser_error (parser, "expected %<(%> or end of line");
- c_parser_skip_to_pragma_eol (parser);
- }
-
+ clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
+ "#pragma omp critical");
stmt = c_parser_omp_structured_block (parser, if_p);
return c_finish_omp_critical (loc, stmt, name, clauses);
}
@@ -18041,7 +18044,8 @@ static tree
c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
tree clauses, tree *cclauses, bool *if_p)
{
- tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
+ tree decl, cond, incr, body, init, stmt, cl;
+ unsigned char save_in_statement;
tree declv, condv, incrv, initv, ret = NULL_TREE;
tree pre_body = NULL_TREE, this_pre_body;
tree ordered_cl = NULL_TREE;
@@ -18109,6 +18113,11 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
for_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
+ /* Forbid break/continue in the loop initializer, condition, and
+ increment expressions. */
+ save_in_statement = in_statement;
+ in_statement = IN_OMP_BLOCK;
+
for (i = 0; i < count; i++)
{
int bracecount = 0;
@@ -18282,10 +18291,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
if (nbraces)
if_p = NULL;
- save_break = c_break_label;
- c_break_label = size_one_node;
- save_cont = c_cont_label;
- c_cont_label = NULL_TREE;
+ in_statement = IN_OMP_FOR;
body = push_stmt_list ();
if (inscan)
@@ -18299,16 +18305,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
}
else
add_stmt (c_parser_c99_block_statement (parser, if_p));
- if (c_cont_label)
- {
- tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
- SET_EXPR_LOCATION (t, loc);
- add_stmt (t);
- }
body = pop_stmt_list (body);
- c_break_label = save_break;
- c_cont_label = save_cont;
+ in_statement = save_in_statement;
while (nbraces)
{
@@ -21537,7 +21536,7 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
gcc_unreachable ();
}
- if (stmt)
+ if (stmt && stmt != error_mark_node)
gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
}
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 10938cf..287b1df 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -547,8 +547,19 @@ extern void gen_aux_info_record (tree, int, int, int);
struct c_spot_bindings;
class c_struct_parse_info;
extern struct obstack parser_obstack;
-extern tree c_break_label;
-extern tree c_cont_label;
+/* Set to IN_ITERATION_STMT if parsing an iteration-statement,
+ to IN_OMP_BLOCK if parsing OpenMP structured block and
+ IN_OMP_FOR if parsing OpenMP loop. If parsing a switch statement,
+ this is bitwise ORed with IN_SWITCH_STMT, unless parsing an
+ iteration-statement, OpenMP block or loop within that switch. */
+#define IN_SWITCH_STMT 1
+#define IN_ITERATION_STMT 2
+#define IN_OMP_BLOCK 4
+#define IN_OMP_FOR 8
+#define IN_OBJC_FOREACH 16
+extern unsigned char in_statement;
+
+extern bool switch_statement_break_seen_p;
extern bool global_bindings_p (void);
extern tree pushdecl (tree);
@@ -609,7 +620,7 @@ extern void shadow_tag_warned (const struct c_declspecs *, int);
extern tree start_enum (location_t, struct c_enum_contents *, tree);
extern bool start_function (struct c_declspecs *, struct c_declarator *, tree);
extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
- tree);
+ tree, location_t * = NULL);
extern tree start_struct (location_t, enum tree_code, tree,
class c_struct_parse_info **);
extern void store_parm_decls (void);
@@ -714,8 +725,8 @@ extern void process_init_element (location_t, struct c_expr, bool,
extern tree build_compound_literal (location_t, tree, tree, bool,
unsigned int);
extern void check_compound_literal_type (location_t, struct c_type_name *);
-extern tree c_start_case (location_t, location_t, tree, bool);
-extern void c_finish_case (tree, tree);
+extern tree c_start_switch (location_t, location_t, tree, bool);
+extern void c_finish_switch (tree, tree);
extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool,
bool);
extern tree build_asm_stmt (bool, tree);
@@ -730,7 +741,7 @@ extern tree c_finish_stmt_expr (location_t, tree);
extern tree c_process_expr_stmt (location_t, tree);
extern tree c_finish_expr_stmt (location_t, tree);
extern tree c_finish_return (location_t, tree, tree);
-extern tree c_finish_bc_stmt (location_t, tree *, bool);
+extern tree c_finish_bc_stmt (location_t, tree, bool);
extern tree c_finish_goto_label (location_t, tree);
extern tree c_finish_goto_ptr (location_t, tree);
extern tree c_expr_to_decl (tree, bool *, bool *);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index fb5c288..dd3e309 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3076,7 +3076,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
if (!(TREE_CODE (fntype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
{
- if (!flag_diagnostics_show_caret)
+ if (!flag_diagnostics_show_caret && !STATEMENT_CLASS_P (function))
error_at (loc,
"called object %qE is not a function or function pointer",
function);
@@ -9956,6 +9956,47 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
goto retry;
}
+/* Expression VALUE coincides with the start of type TYPE in a braced
+ initializer. Return true if we should treat VALUE as initializing
+ the first element of TYPE, false if we should treat it as initializing
+ TYPE as a whole.
+
+ If the initializer is clearly invalid, the question becomes:
+ which choice gives the best error message? */
+
+static bool
+initialize_elementwise_p (tree type, tree value)
+{
+ if (type == error_mark_node || value == error_mark_node)
+ return false;
+
+ gcc_checking_assert (TYPE_MAIN_VARIANT (type) == type);
+
+ tree value_type = TREE_TYPE (value);
+ if (value_type == error_mark_node)
+ return false;
+
+ /* GNU vectors can be initialized elementwise. However, treat any
+ kind of vector value as initializing the vector type as a whole,
+ regardless of whether the value is a GNU vector. Such initializers
+ are valid if and only if they would have been valid in a non-braced
+ initializer like:
+
+ TYPE foo = VALUE;
+
+ so recursing into the vector type would be at best confusing or at
+ worst wrong. For example, when -flax-vector-conversions is in effect,
+ it's possible to initialize a V8HI from a V4SI, even though the vectors
+ have different element types and different numbers of elements. */
+ if (gnu_vector_type_p (type))
+ return !VECTOR_TYPE_P (value_type);
+
+ if (AGGREGATE_TYPE_P (type))
+ return type != TYPE_MAIN_VARIANT (value_type);
+
+ return false;
+}
+
/* Add one non-braced element to the current constructor level.
This adjusts the current position within the constructor's type.
This may also start or terminate implicit levels
@@ -10135,11 +10176,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
else if (value.value != NULL_TREE
- && value.value != error_mark_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
- && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
- || fieldcode == UNION_TYPE
- || gnu_vector_type_p (fieldtype)))
+ && initialize_elementwise_p (fieldtype, value.value))
{
push_init_level (loc, 1, braced_init_obstack);
continue;
@@ -10227,11 +10264,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
else if (value.value != NULL_TREE
- && value.value != error_mark_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
- && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
- || fieldcode == UNION_TYPE
- || gnu_vector_type_p (fieldtype)))
+ && initialize_elementwise_p (fieldtype, value.value))
{
push_init_level (loc, 1, braced_init_obstack);
continue;
@@ -10270,11 +10303,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
else if (value.value != NULL_TREE
- && value.value != error_mark_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
- && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
- || eltcode == UNION_TYPE
- || gnu_vector_type_p (elttype)))
+ && initialize_elementwise_p (elttype, value.value))
{
push_init_level (loc, 1, braced_init_obstack);
continue;
@@ -10779,8 +10808,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
}
struct c_switch {
- /* The SWITCH_EXPR being built. */
- tree switch_expr;
+ /* The SWITCH_STMT being built. */
+ tree switch_stmt;
/* The original type of the testing expression, i.e. before the
default conversion is applied. */
@@ -10797,6 +10826,9 @@ struct c_switch {
warnings crossing decls when branching to a case label. */
struct c_spot_bindings *bindings;
+ /* Whether the switch includes any break statements. */
+ bool break_stmt_seen_p;
+
/* The next node on the stack. */
struct c_switch *next;
@@ -10814,14 +10846,14 @@ struct c_switch {
struct c_switch *c_switch_stack;
/* Start a C switch statement, testing expression EXP. Return the new
- SWITCH_EXPR. SWITCH_LOC is the location of the `switch'.
+ SWITCH_STMT. SWITCH_LOC is the location of the `switch'.
SWITCH_COND_LOC is the location of the switch's condition.
EXPLICIT_CAST_P is true if the expression EXP has an explicit cast. */
tree
-c_start_case (location_t switch_loc,
- location_t switch_cond_loc,
- tree exp, bool explicit_cast_p)
+c_start_switch (location_t switch_loc,
+ location_t switch_cond_loc,
+ tree exp, bool explicit_cast_p)
{
tree orig_type = error_mark_node;
bool bool_cond_p = false;
@@ -10871,18 +10903,19 @@ c_start_case (location_t switch_loc,
}
}
- /* Add this new SWITCH_EXPR to the stack. */
+ /* Add this new SWITCH_STMT to the stack. */
cs = XNEW (struct c_switch);
- cs->switch_expr = build2 (SWITCH_EXPR, orig_type, exp, NULL_TREE);
- SET_EXPR_LOCATION (cs->switch_expr, switch_loc);
+ cs->switch_stmt = build_stmt (switch_loc, SWITCH_STMT, exp,
+ NULL_TREE, orig_type, NULL_TREE);
cs->orig_type = orig_type;
cs->cases = splay_tree_new (case_compare, NULL, NULL);
cs->bindings = c_get_switch_bindings ();
+ cs->break_stmt_seen_p = false;
cs->bool_cond_p = bool_cond_p;
cs->next = c_switch_stack;
c_switch_stack = cs;
- return add_stmt (cs->switch_expr);
+ return add_stmt (cs->switch_stmt);
}
/* Process a case label at location LOC. */
@@ -10918,12 +10951,12 @@ do_case (location_t loc, tree low_value, tree high_value)
}
if (c_check_switch_jump_warnings (c_switch_stack->bindings,
- EXPR_LOCATION (c_switch_stack->switch_expr),
+ EXPR_LOCATION (c_switch_stack->switch_stmt),
loc))
return NULL_TREE;
label = c_add_case_label (loc, c_switch_stack->cases,
- SWITCH_COND (c_switch_stack->switch_expr),
+ SWITCH_STMT_COND (c_switch_stack->switch_stmt),
low_value, high_value);
if (label == error_mark_node)
label = NULL_TREE;
@@ -10934,20 +10967,22 @@ do_case (location_t loc, tree low_value, tree high_value)
controlling expression of the switch, or NULL_TREE. */
void
-c_finish_case (tree body, tree type)
+c_finish_switch (tree body, tree type)
{
struct c_switch *cs = c_switch_stack;
location_t switch_location;
- SWITCH_BODY (cs->switch_expr) = body;
+ SWITCH_STMT_BODY (cs->switch_stmt) = body;
/* Emit warnings as needed. */
- switch_location = EXPR_LOCATION (cs->switch_expr);
+ switch_location = EXPR_LOCATION (cs->switch_stmt);
c_do_switch_warnings (cs->cases, switch_location,
- type ? type : TREE_TYPE (cs->switch_expr),
- SWITCH_COND (cs->switch_expr), cs->bool_cond_p);
- if (c_switch_covers_all_cases_p (cs->cases, TREE_TYPE (cs->switch_expr)))
- SWITCH_ALL_CASES_P (cs->switch_expr) = 1;
+ type ? type : SWITCH_STMT_TYPE (cs->switch_stmt),
+ SWITCH_STMT_COND (cs->switch_stmt), cs->bool_cond_p);
+ if (c_switch_covers_all_cases_p (cs->cases,
+ SWITCH_STMT_TYPE (cs->switch_stmt)))
+ SWITCH_STMT_ALL_CASES_P (cs->switch_stmt) = 1;
+ SWITCH_STMT_NO_BREAK_P (cs->switch_stmt) = !cs->break_stmt_seen_p;
/* Pop the stack. */
c_switch_stack = cs->next;
@@ -10971,110 +11006,9 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
add_stmt (stmt);
}
-/* Emit a general-purpose loop construct. START_LOCUS is the location of
- the beginning of the loop. COND is the loop condition. COND_IS_FIRST
- is false for DO loops. INCR is the FOR increment expression. BODY is
- the statement controlled by the loop. BLAB is the break label. CLAB is
- the continue label. Everything is allowed to be NULL.
- COND_LOCUS is the location of the loop condition, INCR_LOCUS is the
- location of the FOR increment expression. */
-
-void
-c_finish_loop (location_t start_locus, location_t cond_locus, tree cond,
- location_t incr_locus, tree incr, tree body, tree blab,
- tree clab, bool cond_is_first)
-{
- tree entry = NULL, exit = NULL, t;
-
- /* If the condition is zero don't generate a loop construct. */
- if (cond && integer_zerop (cond))
- {
- if (cond_is_first)
- {
- t = build_and_jump (&blab);
- SET_EXPR_LOCATION (t, start_locus);
- add_stmt (t);
- }
- }
- else
- {
- tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-
- /* If we have an exit condition, then we build an IF with gotos either
- out of the loop, or to the top of it. If there's no exit condition,
- then we just build a jump back to the top. */
- exit = build_and_jump (&LABEL_EXPR_LABEL (top));
-
- if (cond && !integer_nonzerop (cond))
- {
- /* Canonicalize the loop condition to the end. This means
- generating a branch to the loop condition. Reuse the
- continue label, if possible. */
- if (cond_is_first)
- {
- if (incr || !clab)
- {
- entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
- t = build_and_jump (&LABEL_EXPR_LABEL (entry));
- }
- else
- t = build1 (GOTO_EXPR, void_type_node, clab);
- SET_EXPR_LOCATION (t, start_locus);
- add_stmt (t);
- }
-
- t = build_and_jump (&blab);
- exit = fold_build3_loc (cond_is_first ? start_locus : input_location,
- COND_EXPR, void_type_node, cond, exit, t);
- }
- else
- {
- /* For the backward-goto's location of an unconditional loop
- use the beginning of the body, or, if there is none, the
- top of the loop. */
- location_t loc = EXPR_LOCATION (expr_first (body));
- if (loc == UNKNOWN_LOCATION)
- loc = start_locus;
- SET_EXPR_LOCATION (exit, loc);
- }
-
- add_stmt (top);
- }
-
- if (body)
- add_stmt (body);
- if (clab)
- add_stmt (build1 (LABEL_EXPR, void_type_node, clab));
- if (incr)
- {
- if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
- {
- t = build0 (DEBUG_BEGIN_STMT, void_type_node);
- SET_EXPR_LOCATION (t, incr_locus);
- add_stmt (t);
- }
- add_stmt (incr);
- }
- if (entry)
- add_stmt (entry);
- if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
- {
- t = build0 (DEBUG_BEGIN_STMT, void_type_node);
- SET_EXPR_LOCATION (t, cond_locus);
- add_stmt (t);
- }
- if (exit)
- add_stmt (exit);
- if (blab)
- add_stmt (build1 (LABEL_EXPR, void_type_node, blab));
-}
-
tree
-c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
+c_finish_bc_stmt (location_t loc, tree label, bool is_break)
{
- bool skip;
- tree label = *label_p;
-
/* In switch statements break is sometimes stylistically used after
a return statement. This can lead to spurious warnings about
control reaching the end of a non-void function when it is
@@ -11082,47 +11016,55 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
language specific tree nodes; this works because
block_may_fallthru returns true when given something it does not
understand. */
- skip = !block_may_fallthru (cur_stmt_list);
+ bool skip = !block_may_fallthru (cur_stmt_list);
- if (!label)
- {
- if (!skip)
- *label_p = label = create_artificial_label (loc);
- }
- else if (TREE_CODE (label) == LABEL_DECL)
- ;
- else switch (TREE_INT_CST_LOW (label))
- {
- case 0:
- if (is_break)
+ if (is_break)
+ switch (in_statement)
+ {
+ case 0:
error_at (loc, "break statement not within loop or switch");
- else
+ return NULL_TREE;
+ case IN_OMP_BLOCK:
+ error_at (loc, "invalid exit from OpenMP structured block");
+ return NULL_TREE;
+ case IN_OMP_FOR:
+ error_at (loc, "break statement used with OpenMP for loop");
+ return NULL_TREE;
+ case IN_ITERATION_STMT:
+ case IN_OBJC_FOREACH:
+ break;
+ default:
+ gcc_assert (in_statement & IN_SWITCH_STMT);
+ c_switch_stack->break_stmt_seen_p = true;
+ break;
+ }
+ else
+ switch (in_statement & ~IN_SWITCH_STMT)
+ {
+ case 0:
error_at (loc, "continue statement not within a loop");
- return NULL_TREE;
-
- case 1:
- gcc_assert (is_break);
- error_at (loc, "break statement used with OpenMP for loop");
- return NULL_TREE;
-
- case 2:
- if (is_break)
- error ("break statement within %<#pragma simd%> loop body");
- else
- error ("continue statement within %<#pragma simd%> loop body");
- return NULL_TREE;
-
- default:
- gcc_unreachable ();
- }
+ return NULL_TREE;
+ case IN_OMP_BLOCK:
+ error_at (loc, "invalid exit from OpenMP structured block");
+ return NULL_TREE;
+ case IN_ITERATION_STMT:
+ case IN_OMP_FOR:
+ case IN_OBJC_FOREACH:
+ break;
+ default:
+ gcc_unreachable ();
+ }
if (skip)
return NULL_TREE;
-
- if (!is_break)
- add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
-
- return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
+ else if (in_statement & IN_OBJC_FOREACH)
+ {
+ /* The foreach expander produces low-level code using gotos instead
+ of a structured loop construct. */
+ gcc_assert (label);
+ return add_stmt (build_stmt (loc, GOTO_EXPR, label));
+ }
+ return add_stmt (build_stmt (loc, (is_break ? BREAK_STMT : CONTINUE_STMT)));
}
/* A helper routine for c_process_expr_stmt and c_finish_stmt_expr. */
@@ -13269,8 +13211,13 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
{
if (length == NULL_TREE)
{
- error_at (OMP_CLAUSE_LOCATION (c),
- "for pointer type length expression must be specified");
+ if (TREE_CODE (ret) == PARM_DECL && C_ARRAY_PARAMETER (ret))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for array function parameter length expression "
+ "must be specified");
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for pointer type length expression must be specified");
return error_mark_node;
}
if (length != NULL_TREE
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 577d8b5..5c0ed82 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -590,7 +590,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
: ENTRY_BLOCK_PTR_FOR_FN (cfun)));
if (basic_block_info_for_fn (cfun)->length () <= (size_t)index)
vec_safe_grow_cleared (basic_block_info_for_fn (cfun),
- index + 1);
+ index + 1, true);
SET_BASIC_BLOCK_FOR_FN (cfun, index, bb);
if (last_basic_block_for_fn (cfun) <= index)
last_basic_block_for_fn (cfun) = index + 1;
@@ -617,7 +617,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
loop->num = is_loop_header_of;
loop->header = bb;
vec_safe_grow_cleared (loops_for_fn (cfun)->larray,
- is_loop_header_of + 1);
+ is_loop_header_of + 1, true);
(*loops_for_fn (cfun)->larray)[is_loop_header_of] = loop;
flow_loop_tree_node_add (loops_for_fn (cfun)->tree_root,
loop);