aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.7/gcc/cfgexpand.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.7/gcc/cfgexpand.c')
-rw-r--r--gcc-4.7/gcc/cfgexpand.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/gcc-4.7/gcc/cfgexpand.c b/gcc-4.7/gcc/cfgexpand.c
index bde15f696..53066e031 100644
--- a/gcc-4.7/gcc/cfgexpand.c
+++ b/gcc-4.7/gcc/cfgexpand.c
@@ -1508,15 +1508,39 @@ estimated_stack_frame_size (struct cgraph_node *node)
return size;
}
+/* Helper routine to check if a record or union contains an array field. */
+
+static int
+record_or_union_type_has_array_p (const_tree tree_type)
+{
+ tree fields = TYPE_FIELDS (tree_type);
+ tree f;
+
+ for (f = fields; f; f = DECL_CHAIN (f))
+ {
+ if (TREE_CODE (f) == FIELD_DECL)
+ {
+ tree field_type = TREE_TYPE (f);
+ if (RECORD_OR_UNION_TYPE_P (field_type))
+ return record_or_union_type_has_array_p (field_type);
+ if (TREE_CODE (field_type) == ARRAY_TYPE)
+ return 1;
+ }
+ }
+ return 0;
+}
+
/* Expand all variables used in the function. */
static void
expand_used_vars (void)
{
tree var, outer_block = DECL_INITIAL (current_function_decl);
+ referenced_var_iterator rvi;
VEC(tree,heap) *maybe_local_decls = NULL;
unsigned i;
unsigned len;
+ int gen_stack_protect_signal = 0;
/* Compute the phase of the stack frame for this function. */
{
@@ -1549,6 +1573,23 @@ expand_used_vars (void)
}
}
+ FOR_EACH_REFERENCED_VAR (cfun, var, rvi)
+ if (!is_global_var (var))
+ {
+ tree var_type = TREE_TYPE (var);
+ /* Examine local referenced variables that have their addresses taken,
+ contain an array, or are arrays. */
+ if (TREE_CODE (var) == VAR_DECL
+ && (TREE_CODE (var_type) == ARRAY_TYPE
+ || TREE_ADDRESSABLE (var)
+ || (RECORD_OR_UNION_TYPE_P (var_type)
+ && record_or_union_type_has_array_p (var_type))))
+ {
+ ++gen_stack_protect_signal;
+ break;
+ }
+ }
+
/* At this point all variables on the local_decls with TREE_USED
set are not associated with any block scope. Lay them out. */
@@ -1639,11 +1680,18 @@ expand_used_vars (void)
dump_stack_var_partition ();
}
- /* There are several conditions under which we should create a
- stack guard: protect-all, alloca used, protected decls present. */
- if (flag_stack_protect == 2
- || (flag_stack_protect
- && (cfun->calls_alloca || has_protected_decls)))
+ /* Create stack guard, if
+ a) "-fstack-protector-all" - always;
+ b) "-fstack-protector-strong" - if there are arrays, memory
+ references to local variables, alloca used, or protected decls present;
+ c) "-fstack-protector" - if alloca used, or protected decls present */
+ if (flag_stack_protect == 3 /* -fstack-protector-all */
+ || (flag_stack_protect == 2 /* -fstack-protector-strong */
+ && (gen_stack_protect_signal || cfun->calls_alloca
+ || has_protected_decls))
+ || (flag_stack_protect == 1 /* -fstack-protector */
+ && (cfun->calls_alloca
+ || has_protected_decls)))
create_stack_guard ();
/* Assign rtl to each variable based on these partitions. */